Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,4 @@ WORKDIR packages/node
EXPOSE 1031

# Define the command to run when the container starts
CMD ["npm", "start:bcn"]
CMD ["npm", "start:bcn"]
30,192 changes: 16,503 additions & 13,689 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion packages/TBC20/build/src/token.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { Contract } from '@bitcoin-computer/lib';
export declare class Token extends Contract {
amount: bigint;
name: string;
Expand Down
1 change: 0 additions & 1 deletion packages/TBC20/build/src/token.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { Contract } from '@bitcoin-computer/lib';
export class Token extends Contract {
constructor(to, amount, name, symbol = '') {
super({ _owners: [to], amount, name, symbol });
Expand Down
2 changes: 0 additions & 2 deletions packages/TBC20/src/token.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { Contract } from '@bitcoin-computer/lib'

type Constructor<T> = new (...args: any[]) => T

export class Token extends Contract {
Expand Down
16 changes: 8 additions & 8 deletions packages/TBC20/test/token.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { expect } from 'chai'
import { Computer } from '@bitcoin-computer/lib'
import { Computer, SmartContract } from '@bitcoin-computer/lib'
import dotenv from 'dotenv'
import { Token, TokenHelper } from '../src/token.js'
import path from 'path'
Expand Down Expand Up @@ -32,7 +32,7 @@ before(async () => {
})

describe('Token', async () => {
let token1: Token
let token1: SmartContract<typeof Token>

describe('mint', async () => {
it('Sender mints 3 tokens', async () => {
Expand All @@ -51,11 +51,11 @@ describe('Token', async () => {
})

describe('transfer, merge and burn', () => {
let token2: Token
let token2After: Token
let token2: SmartContract<typeof Token>
let token2After: SmartContract<typeof Token>

it('Sender transfers 1 token to Receiver', async () => {
token2 = (await token1.transfer(receiver.getPublicKey(), 1n)) as Token
token2 = await token1.transfer(receiver.getPublicKey(), 1n)
})

it('The meta data of token should be set correctly', () => {
Expand All @@ -81,12 +81,12 @@ describe('Token', async () => {
it('computer.getOUTXOs should return the tokens', async () => {
const senderRevs = await sender.getOUTXOs({ publicKey: sender.getPublicKey() })
expect(senderRevs.length).eq(1)
const senderToken = (await sender.sync(senderRevs[0])) as Token
const senderToken = await sender.sync<typeof Token>(senderRevs[0])
expect(senderToken.amount).eq(2n)

const receiverRevs = await receiver.getOUTXOs({ publicKey: receiver.getPublicKey() })
expect(receiverRevs.length).eq(1)
const receiverTokens = (await receiver.sync(receiverRevs[0])) as Token
const receiverTokens = await receiver.sync<typeof Token>(receiverRevs[0])
expect(receiverTokens.amount).eq(1n)
})

Expand Down Expand Up @@ -114,7 +114,7 @@ describe('Token', async () => {

const { env } = effect
const { __bc__ } = env
token2After = __bc__ as unknown as Token
token2After = __bc__ as SmartContract<typeof Token>

expect(token1._owners).deep.eq([sender.getPublicKey()])
expect(token2After._owners).deep.eq([sender.getPublicKey()])
Expand Down
3 changes: 2 additions & 1 deletion packages/TBC721/build/src/nft.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { SmartContract } from '@bitcoin-computer/lib';
export declare class NFT extends Contract {
name: string;
artist: string;
Expand All @@ -20,7 +21,7 @@ export declare class NftHelper implements ITBC721 {
mod: string | undefined;
constructor(computer: any, mod?: string);
deploy(): Promise<string>;
mint(name: string, artist: string, url: string): Promise<NFT>;
mint(name: string, artist: string, url: string): Promise<SmartContract<typeof NFT>>;
balanceOf(publicKey: string): Promise<number>;
ownersOf(tokenId: string): Promise<string[]>;
transfer(to: string, tokenId: string): Promise<void>;
Expand Down
4 changes: 3 additions & 1 deletion packages/TBC721/src/nft.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { SmartContract } from '@bitcoin-computer/lib'

export class NFT extends Contract {
name: string
artist: string
Expand Down Expand Up @@ -41,7 +43,7 @@ export class NftHelper implements ITBC721 {
return this.mod
}

async mint(name: string, artist: string, url: string): Promise<NFT> {
async mint(name: string, artist: string, url: string): Promise<SmartContract<typeof NFT>> {
const { tx, effect } = await this.computer.encode({
exp: `new NFT("${name}", "${artist}", "${url}")`,
mod: this.mod,
Expand Down
18 changes: 8 additions & 10 deletions packages/TBC721/test/nft.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as chai from 'chai'
import { Computer } from '@bitcoin-computer/lib'
import { Computer, SmartContract } from '@bitcoin-computer/lib'
import dotenv from 'dotenv'
import chaiMatchPattern from 'chai-match-pattern'
import { NFT, NftHelper } from '../src/nft.js'
Expand Down Expand Up @@ -45,7 +45,7 @@ describe('NFT', () => {
let initialRoot: string

describe('Using NFTs without an helper class', () => {
let nft: NFT
let nft: SmartContract<typeof NFT>

describe('Minting an NFT', () => {
const sender = new Computer({ url, chain, network })
Expand All @@ -56,7 +56,6 @@ describe('NFT', () => {

it('Sender mints an NFT', async () => {
nft = await sender.new(NFT, ['Test'])
// @ts-ignore
expect(nft).matchPattern({ name: 'Test', artist, url: imageUrl, ...meta })

// Property _owners is a singleton array with minters public key
Expand All @@ -68,21 +67,20 @@ describe('NFT', () => {
initialId = nft._id
initialRev = nft._rev
initialRoot = nft._root

// The nft is returned when syncing against it's revision
expect(await sender.sync(nft._rev)).deep.eq(nft)

// Transferring an NFT'
const receiver = new Computer({ url, chain, network })

// Sender transfers the NFT to receiver
await nft.transfer(receiver.getPublicKey())
// @ts-ignore
expect(nft).to.matchPattern({ name: 'Test', artist, url: imageUrl, ...meta })

// The id does not change
expect(initialId).eq(nft._id)

// The revision is updated
expect(initialRev).not.eq(nft._rev)

Expand All @@ -91,7 +89,7 @@ describe('NFT', () => {

// The _owners are updated to receiver's public key
expect(nft._owners).deep.eq([receiver.getPublicKey()])

// Syncing to the NFT's revision returns an object that is equal to the NFT
expect(await receiver.sync(nft._rev)).deep.eq(nft)
})
Expand All @@ -102,7 +100,7 @@ describe('NFT', () => {
const computer = new Computer({ url, chain, network })

let nftHelper: NftHelper
let nft: NFT
let nft: SmartContract<typeof NFT>

before(async () => {
await computer.faucet(1e8)
Expand Down
6 changes: 3 additions & 3 deletions packages/chat/src/components/Chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ const ChatInput = ({
time: Date.now().toString(),
}
const latesRev = await computer.latest(chatId)
const chatObj = (await computer.sync(latesRev)) as ChatSc
const chatObj = await computer.sync<typeof ChatSc>(latesRev)
await chatObj.post(JSON.stringify(messageData))
await sleep(2000)
await refreshChat()
Expand Down Expand Up @@ -290,7 +290,7 @@ export function Chat({ chatId }: { chatId: string }) {
try {
showLoader(true)
const latesRev = await computer.latest(id)
const synced = (await computer.sync(latesRev)) as ChatSc
const synced = await computer.sync<typeof ChatSc>(latesRev)
setChatObj(synced)
const messagesData: messageI[] = []
synced.messages.forEach((message) => {
Expand All @@ -300,7 +300,7 @@ export function Chat({ chatId }: { chatId: string }) {
showLoader(false)
} catch {
showLoader(false)
showSnackBar('Not a valid Chat', false)
showSnackBar('Not a valid Chat ', false)
}
}

Expand Down
7 changes: 4 additions & 3 deletions packages/chat/src/components/Chats.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { HiPlusCircle } from 'react-icons/hi'
import { VITE_CHAT_MOD_SPEC } from '../constants/modSpecs'
import { ChatSc } from '../contracts/chat'
import { Chat } from './Chat'
import { SmartContract } from '@bitcoin-computer/lib'

const newChatModal = 'new-chat-modal'

Expand All @@ -30,7 +31,7 @@ function CreateNewChat() {
if (typeof effect.res === 'object' && !Array.isArray(effect.res)) {
showLoader(false)
showSnackBar('You created a new chat', true)
navigate(`/chats/${effect.res?._id as string}`)
navigate(`/chats/${(effect.res as SmartContract<typeof ChatSc>)._id}`)
window.location.reload()
}
} catch (err) {
Expand Down Expand Up @@ -89,7 +90,7 @@ export function Chats() {
const result = await computer.getOUTXOs({ mod: VITE_CHAT_MOD_SPEC, publicKey })
const chatsPromise: Promise<ChatSc>[] = []
result.forEach((rev: string) => {
chatsPromise.push(computer.sync(rev) as Promise<ChatSc>)
chatsPromise.push(computer.sync<typeof ChatSc>(rev))
})

Promise.allSettled(chatsPromise).then((results) => {
Expand All @@ -111,7 +112,7 @@ export function Chats() {
unsubscribe = await computer.streamTXOs(
{ mod: VITE_CHAT_MOD_SPEC },
async ({ rev }) => {
const newChat = (await computer.sync(rev)) as ChatSc
const newChat = await computer.sync<typeof ChatSc>(rev)
// Filter by ownership
if (newChat._owners.includes(publicKey)) {
setChats((prev) => {
Expand Down
4 changes: 3 additions & 1 deletion packages/chat/src/components/Mint.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { useContext, useState } from 'react'
import { ComputerContext, Modal } from '@bitcoin-computer/components'
import { Link } from 'react-router-dom'
import { VITE_CHAT_MOD_SPEC } from '../constants/modSpecs'
import { SmartContract } from '@bitcoin-computer/lib'
import { ChatSc } from '../contracts/chat'

function SuccessContent(rev: string) {
return (
Expand Down Expand Up @@ -72,7 +74,7 @@ export default function Mint() {
})
await computer.broadcast(tx)
if (typeof effect.res === 'object' && !Array.isArray(effect.res)) {
setSuccessRev(effect.res?._id as string)
setSuccessRev((effect.res as SmartContract<typeof ChatSc>)._id as string)
Modal.showModal('success-modal')
} else {
setErrorMsg('Error occurred while creating chat')
Expand Down
2 changes: 2 additions & 0 deletions packages/chat/src/contracts/chat.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
export class ChatSc extends Contract {
messages!: string[]
channelName!: string
_owners!: string[]

constructor(channelName: string, publicKey: string) {
super({
messages: [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export const ChallengeListWrapper = ({ user }: { user: User | null }) => {
const challengeSyncPromises: Promise<ChessChallengeTxWrapper>[] = []

challengeRevs.forEach((rev) => {
challengeSyncPromises.push(computer.sync(rev) as Promise<ChessChallengeTxWrapper>)
challengeSyncPromises.push(computer.sync<typeof ChessChallengeTxWrapper>(rev))
})

const challengesList = await Promise.all(challengeSyncPromises)
Expand Down
30 changes: 15 additions & 15 deletions packages/chess-app/src/components/ChessBoard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { NewGameModal, newGameModal } from './NewGame'
import { Piece } from 'react-chessboard/dist/chessboard/types'
import { CreateUserModal, creaetUserModal } from './CreateUser'
import { ChallengeListWrapper } from './ChallengesListWrapper'
import { Computer } from '@bitcoin-computer/lib'
import { Computer, precise, SmartContract } from '@bitcoin-computer/lib'
import { GamesListWrapper } from './GamesListWrapper'

const winnerModal = 'winner-modal'
Expand All @@ -38,7 +38,7 @@ function currentPlayer(fen: string) {
throw new Error('Invalid FEN: Unknown active color')
}

function getWinnerPubKey(chessContract: ChessContract) {
function getWinnerPubKey(chessContract: SmartContract<typeof ChessContract>) {
const chessLibrary = new ChessLib(chessContract.fen)
const { publicKeyW, publicKeyB } = chessContract
if (chessLibrary.isCheckmate()) return chessLibrary.turn() === 'b' ? publicKeyW : publicKeyB
Expand Down Expand Up @@ -131,7 +131,7 @@ function WinnerModal(data: { winnerPubKey: string; userPubKey: string; amount: s
const renderButtonContent = (
game: ChessLib | undefined,
paymentReleased: boolean,
chessContract: ChessContract | null,
chessContract: SmartContract<typeof ChessContract> | null,
computer: Computer,
requestRelease: () => Promise<void>,
releaseFund: () => Promise<void>,
Expand Down Expand Up @@ -185,16 +185,18 @@ export function ChessBoard() {
const [orientation, setOrientation] = useState<'white' | 'black'>('white')
const [winnerData, setWinnerData] = useState({})
const [game, setGame] = useState<ChessLib | null>(null)
const [chessContract, setChessContract] = useState<ChessContract | null>(null)
const [chessContract, setChessContract] = useState<SmartContract<typeof ChessContract> | null>(
null,
)
const [chessContractId, setChessContractId] = useState<string>('')
const [user, setUser] = useState<User | null>(null)
const [balance, setBalance] = useState<bigint>(0n)
const [paymentReleased, setPaymentReleased] = useState(true)

const computer = useContext(ComputerContext)
const fetchChessContract = async (): Promise<ChessContract> => {
const fetchChessContract = async (): Promise<SmartContract<typeof ChessContract>> => {
const latest = await computer.latest(gameId)
return computer.sync(latest) as Promise<ChessContract>
return computer.sync<typeof ChessContract>(latest)
}

useEffect(() => {
Expand All @@ -218,7 +220,7 @@ export function ChessBoard() {
setChessContract(chessContract)
setGame(new ChessLib(chessContract.fen))
const walletBalance = await computer.getBalance()
setBalance(walletBalance.balance as unknown as bigint)
setBalance(walletBalance.balance as bigint)
}
} catch (error) {
console.error('Error fetching contract:', error)
Expand All @@ -237,7 +239,7 @@ export function ChessBoard() {
if (!userRev) {
Modal.showModal(creaetUserModal)
} else {
const userObj = (await computer.sync(userRev)) as User
const userObj = await computer.sync<typeof User>(userRev)
setUser(userObj)
}
} catch (error) {
Expand All @@ -264,7 +266,7 @@ export function ChessBoard() {
setGame(new ChessLib(cc.fen))
setOrientation(cc.publicKeyW === computer.getPublicKey() ? 'white' : 'black')
const walletBalance = await computer.getBalance()
setBalance(walletBalance.balance as unknown as bigint)
setBalance(walletBalance.balance as bigint)
}
} catch (error) {
console.log(error)
Expand Down Expand Up @@ -305,7 +307,7 @@ export function ChessBoard() {
const subscribeToWinnerTx = async () => {
close = await computer.subscribe(cc.winnerTxWrapper._id, async (rev) => {
if (rev) {
const txWrapper = (await computer.sync(rev.rev)) as WinnerTxWrapper
const txWrapper = await computer.sync<typeof WinnerTxWrapper>(rev.rev)
if (txWrapper.redeemTxHex) {
// Explicitly fetching chess contract again to get the latest state
const chessContract = await fetchChessContract()
Expand Down Expand Up @@ -432,11 +434,9 @@ export function ChessBoard() {
showSnackBar('Not a valid chess contract', false)
return
}
const signedRedeemTx = await signRedeemTx(
computer,
chessContract,
chessContract?.winnerTxWrapper,
)
const { winnerTxWrapper } = chessContract
precise<typeof WinnerTxWrapper>(winnerTxWrapper)
const signedRedeemTx = await signRedeemTx(computer, chessContract, winnerTxWrapper)
const finalTxId = await computer.broadcast(signedRedeemTx)
setPaymentReleased(true)
showSnackBar(`You lost the game, fund released. Transaction: ${finalTxId}`, true)
Expand Down
2 changes: 1 addition & 1 deletion packages/chess-app/src/components/CreateUser.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export function CreateUserModalContent({
const userHelper = new UserHelper({ computer, mod: VITE_CHESS_USER_MOD_SPEC })
const txId = await userHelper.createUser(userName)
const rev = await computer.latest(txId + ':0')
const user = (await computer.sync(rev)) as User
const user = await computer.sync<typeof User>(rev)
setUser(user)
setUserTxId(txId)
setTitle('Account created successfully!')
Expand Down
Loading