Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
12 changes: 6 additions & 6 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ README.md
packages/.DS_Store
packages/nakamotojs/test
packages/nakamotojs/ts_src
packages/.turbo
packages/node/coverage/
packages/node/logs/
packages/node/node_modules/
Expand All @@ -22,26 +23,25 @@ packages/node/.DS_Store
packages/node/src
packages/node/test
packages/node/*.log
packages/node/*.conf
packages/node/scripts/__pycache__

packages/lib/*.log

packages/chat
packages/chess-app
packages/chess-contracts
packages/chess-server
packages/components
packages/cra-template
packages/docs
packages/explorer
packages/explorer-vite
packages/ft
packages/ft2
packages/nft
packages/nft-vite
packages/nodejs-template
packages/swap/
packages/nft-vite
packages/TBC*/
packages/vite-template
packages/wallet
packages/wallet-vite
packages/website

.env
Expand Down
2 changes: 1 addition & 1 deletion packages/chat/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<div align="center">
<h1>TBC Chat</h1>
<h1>Bitcoin Computer Chat</h1>
<p>
A chat that's as stable as Bitcoin and Litecoin
<br />
Expand Down
10 changes: 0 additions & 10 deletions packages/chat/src/contracts/counter.ts

This file was deleted.

4 changes: 2 additions & 2 deletions packages/chess-app/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Chess App
# Bitcoin Computer Chess App

## Usage

Start a Bitcoin Computer Node in the package `node`. Then copy the `.env.example` file.
Start a Bitcoin Computer Node in the package `node`. Then copy the `.env.example` file.

```
cp .env.example .env
Expand Down
2 changes: 1 addition & 1 deletion packages/chess-contracts/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Chess Contracts
# Bitcoin Computer Chess Contracts

## Usage

Expand Down
2 changes: 1 addition & 1 deletion packages/chess-server/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Chess Server
# Bitcoin Computer Chess Server

## Usage

Expand Down
19 changes: 10 additions & 9 deletions packages/components/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<div align="center">
<h1>TBC Components</h1>
<h1>Bitcoin Computer Components</h1>
<p>
A component library for smart contract driven applications
<br />
Expand All @@ -13,16 +13,17 @@
This package contains components that are used in several applications. Have a look at the other packages for how to use.

Currently it contains the following:
* [Auth](./src/Auth.tsx) - Login and logout
* [Wallet](./src/Wallet.tsx) - Deposit cryptocurrency
* [Gallery](./src/Gallery.tsx) - displays a grid of smart objects
* [SmartObject](./src/SmartObject.tsx) - displays a smart object and has a form for each of its methods
* [Transaction](./src/Transaction.tsx) - displays a transaction including its TBC expression if it has one
* [Modal](./src/Wallet.tsx) - displays a modal window

- [Auth](./src/Auth.tsx) - Login and logout
- [Wallet](./src/Wallet.tsx) - Deposit cryptocurrency
- [Gallery](./src/Gallery.tsx) - displays a grid of smart objects
- [SmartObject](./src/SmartObject.tsx) - displays a smart object and has a form for each of its methods
- [Transaction](./src/Transaction.tsx) - displays a transaction including its Bitcoin Computer expression if it has one
- [Modal](./src/Wallet.tsx) - displays a modal window

## Use

To re-build the code run
To re-build the code run

<font size=1>

Expand All @@ -36,4 +37,4 @@ You might have to restart the applications.

## Legal Notice

See [here](https://github.com/bitcoin-computer/monorepo/tree/main/packages/lib#legal-notice).
See [here](https://github.com/bitcoin-computer/monorepo/tree/main/packages/lib#legal-notice).
6 changes: 6 additions & 0 deletions packages/docs/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"printWidth": 100,
"semi": false,
"singleQuote": true,
"trailingComma": "all"
}
22 changes: 13 additions & 9 deletions packages/docs/Examples/chat.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ icon: comment-discussion

## Smart Contract

A chat is just a smart object with a property `messages` of type `string[]`. Like all smart objects it has an `_owners` property set to the current data owner. The [`_readers`](./how-it-works.md#keyword-properties-control-the-transaction-being-built) property can be used to restrict read access.
A chat is just a smart object with a property `messages` of type `string[]`. Like all smart objects it has an `_owners` property set to the current data owner. The [`_readers`](./how-it-works.md#keyword-properties-control-the-transaction-being-built) property can be used to restrict read access.

```ts
class Chat extends Contract {
Expand All @@ -19,7 +19,7 @@ class Chat extends Contract {
super({
messages: [],
_owners: publicKeys,
_readers: publicKeys
_readers: publicKeys,
})
}

Expand All @@ -28,15 +28,15 @@ class Chat extends Contract {
}

remove(publicKey: string) {
this._readers = this._readers.filter(o => o !== publicKey)
this._owners_ = this._owners_.filter(o => o !== publicKey)
this._readers = this._readers.filter((o) => o !== publicKey)
this._owners_ = this._owners_.filter((o) => o !== publicKey)
}
}
```

## Usage

A new chat can be created using the [`new`](./API/new.md) function. Note that Bob can initially post to the chat and read it's state as Bob's public key was added to the `_owners` array and `_readers` array by Alice upon creation of the chat.
A new chat can be created using the [`new`](./API/new.md) function. Note that Bob can initially post to the chat and read it's state as Bob's public key was added by Alice to the `_owners` array and to the `_readers` array upon creation of the chat.

Later, Alice called the `remove` function removing Bob's public key from these arrays. After this point Bob cannot read or write anymore.

Expand All @@ -58,7 +58,7 @@ const alicesChat = await alice.new(Chat, [publicKeys])
await alicesChat.post('Hi')

// Bob can read the current state of the chat and post a message
const bobsChat = await bob.sync(alicesChat._rev) as Chat
const bobsChat = (await bob.sync(alicesChat._rev)) as Chat
await bobsChat.post('Yo')
expect(bobsChat.messages).deep.eq(['Hi', 'Yo'])

Expand All @@ -67,7 +67,7 @@ try {
// This line throws an error
await eve.sync(alicesChat._rev)
expect(true).eq(false)
} catch(err) {
} catch (err) {
expect(err.message).not.undefined
}

Expand All @@ -79,7 +79,11 @@ try {
// This line throws an error
await bob.sync(alicesChat._rev)
expect(true).eq(false)
} catch(err) {
} catch (err) {
expect(err.message).not.undefined
}
```
```

## Code

You can find the code [here](https://github.com/bitcoin-computer/monorepo/blob/main/packages/chat/README.md).
27 changes: 13 additions & 14 deletions packages/docs/Examples/fungible-token.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,24 @@ icon: circle

## Smart Contract

A fungible token has three properties, a `supply` indicating the number of tokens stored in the current smart object, a property `totalSupply` that that stores the number of tokens that were created during the mint, and an `_owners` property set to the current owner of the smart object.
A fungible token has three properties, a `amount` indicating the number of tokens stored in the current smart object, a property `symbol` that stores the identifier of the tokens, and an `_owners` property set to the current owner of the smart object.

The `transfer` function takes two arguments, an `amount` to be sent and the public key of the recipient. This function first checks if the current smart object contains sufficient supply and throws an error if it does not. If the supply is sufficient the supply of the current smart object is reduced by the amount to be sent. A new smart object is created that is owned by recipient and that contains the amount to be sent. This object is returned from the function call to create a new smart object.
The `transfer` function takes two arguments, the public key of the recipient and an `amount` to be sent. This function first checks if the current smart object contains sufficient supply and throws an error if it does not. If the supply is sufficient the supply of the current smart object is reduced by the amount to be sent. A new smart object is created that is owned by recipient and that contains the amount to be sent. This object is returned from the function call to create a new smart object.

```ts
```javascript
class Token extends Contract {
supply: number
totalSupply: number
amount: number
symbol: string
_owners: string[]

constructor(to: string, supply: number, totalSupply: number) {
super({ supply, totalSupply, _owners: [to] })
constructor(to: string, amount: number, symbol: string) {
super({ _owners: [to], amount, symbol })
}

transfer(amount: number, recipient: string) {
if (this.supply < amount) throw new Error()
this.supply -= amount
return new Token(recipient, amount, this.totalSupply)
transfer(recipient: string, amount: number) {
if (this.amount < amount) throw new Error()
this.amount -= amount
return new Token(recipient, amount, this.symbol)
}
}
```
Expand All @@ -42,14 +42,13 @@ const receiver = new Computer()
await sender.faucet(0.001e8)

// Mint new fungible token with total supply of 10
const token = await sender.new(Token, [sender.getPublicKey(), 10, 10])
const token = await sender.new(Token, [sender.getPublicKey(), 10, 'MY-TOKEN'])

// Send 2 tokens to receiver, sentToken will have supply of 2 and
// token will have a supply of 8.
const sentToken = await token.transfer(2, receiver.getPublicKey())
const sentToken = await token.transfer(receiver.getPublicKey(), 2)
```

## Code

You can find the code [here](https://github.com/bitcoin-computer/monorepo/tree/main/packages/TBC20#readme).

4 changes: 2 additions & 2 deletions packages/docs/Examples/non-fungible-token.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ If more than one NFT are broadcast one can save transaction fees by broadcasting

```ts
// Create wallet
const sender = new Computer(RLTC)
const sender = new Computer()

// Fund wallet
await sender.faucet(0.001e8)
Expand All @@ -58,7 +58,7 @@ await tokenHelper.deploy()
nft = await tokenHelper.mint('name', 'symbol')

// Transfer NFT
await tokenHelper.transfer(nft._id, new Computer().getPublicKey())
await tokenHelper.transfer(new Computer().getPublicKey(), nft._id)
```

## Code
Expand Down
15 changes: 7 additions & 8 deletions packages/docs/Examples/sale.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ These examples use several advanced features (sighash types, mocking, and contro

We first explain a simpler version that works for the Bitcoin Computer but not for ordinals. The [next](#ordinals-sale) section explains a version that can be used with ordinals.

Seller needs to build a partial transaction containing an input spending the asset and an output for receiving the payment. The [sighash type](https://developer.bitcoin.org/devguide/transactions.html#signature-hash-types) `SIGHASH_SINGLE | SIGHASH_ANYONECANPAY` allows Seller to sign only the first input and output.
Seller needs to build a partial transaction containing an input spending the asset and an output for receiving the payment. The [sighash type](https://developer.bitcoin.org/devguide/transactions.html#signature-hash-types) `SIGHASH_SINGLE | SIGHASH_ANYONECANPAY` allows Seller to sign only the first input and output.

Buyer wants to obtain the smart object in the first input so Buyer is incentivized to build the transaction according to the protocol. If he broadcasts transaction that is invalid in the Bitcoin Computer protocol, Buyer destroys the smart object but pays the Seller.

Expand All @@ -39,7 +39,7 @@ export class Sale extends Contract {

The first argument to the `exec` function is an nft of the following class.

```ts
```javascript
export class NFT extends Contract {
constructor(name = '', symbol = '') {
super({ name, symbol })
Expand Down Expand Up @@ -109,7 +109,7 @@ class PaymentMock {
const mock = new PaymentMock(1e8)
```

Now Seller is ready to create and sign the partial sale transaction using as shown below. There is a lot going on, so we will break down the arguments below.
Now Seller is ready to create and sign the partial sale transaction using as shown below. There is a lot going on here, so we will break down the arguments below.

```ts
const { tx } = await seller.encode({
Expand Down Expand Up @@ -165,10 +165,10 @@ Next, Buyer updates the second input of the transaction that currently spends th
tx.updateInput(1, { txId: paymentTxId, index: parseInt(paymentIndex, 10) })
```

Then Buyer updates the second output to contain Buyer's public key. This ensures that Buyer will be new owner of the nft.
Then Buyer updates the second output to contain Buyer's public key. This ensures that Buyer will be new owner of the nft.

```ts
tx.updateOutput(1, { scriptPubKey: buyer.toScriptPubKey()})
tx.updateOutput(1, { scriptPubKey: buyer.toScriptPubKey() })
```

Finally Buyer funds, signs, and broadcasts to execute the sale.
Expand Down Expand Up @@ -282,8 +282,7 @@ await bob.broadcast(finalTx)

The `Sale` smart contract is not safe to use with ordinals because the smart objects have different ordinal ranges before and after the call. To preserve the ordinal ranges the expression must not use the `_amount` keyword and must not return an object or an array containing an object.

Building a sale contract for ordinals is more complicated than for smart objects. A very clever construction was proposed by Rodarmor [here](https://github.com/ordinals/ord/issues/802) and later [refined](https://github.com/ordinals/ord/issues/802#issuecomment-1498030294). Our smart contract below implements this exact idea.

Building a sale contract for ordinals is more complicated than for smart objects. A very clever construction was proposed by Rodarmor [here](https://github.com/ordinals/ord/issues/802) and later [refined](https://github.com/ordinals/ord/issues/802#issuecomment-1498030294). Our smart contract below implements this exact idea.

### Smart Contracts

Expand Down Expand Up @@ -379,7 +378,7 @@ const [paymentTxId, paymentIndex] = payment._rev.split(':')
tx.updateInput(1, { txId: paymentTxId, index: parseInt(paymentIndex, 10) })

// Buyer updates the second output of the swap tx to receive the NFT
tx.updateOutput(1, { scriptPubKey: buyer.toScriptPubKey()})
tx.updateOutput(1, { scriptPubKey: buyer.toScriptPubKey() })

// Buyer funds, signs, and broadcasts to execute the sale
await buyer.fund(tx)
Expand Down
19 changes: 11 additions & 8 deletions packages/docs/Examples/swap.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ We note that the definition of a token swap differs wildly from the legal defini

## Swap Using a Static Function

You can build a swap as a static function that takes two arguments and exchanges their owners. This method preserves ordinal ranges, so it is safe to use this smart objects that contain ordinals.
You can build a swap as a static function that takes two arguments and exchanges their owners. This method preserves ordinal ranges, so it is safe to use this in smart objects that contain ordinals.

### Smart Contracts

Expand All @@ -29,9 +29,10 @@ export class StaticSwap extends Contract {
}
}
```
The code below shows the `NFT` class. While this example uses NFTs as arguments, the same function can be used to swap any pair of smart objects that have a `transfer` function.

```ts
The code below shows the `NFT` class. While this example uses NFTs as arguments, the same function can be used to swap any pair of smart objects that have a `transfer` function.

```javascript
export class NFT extends Contract {
constructor(name = '', symbol = '') {
super({ name, symbol })
Expand All @@ -54,9 +55,9 @@ const b = await alice.new(NFT, ['B', 'BBB'])

### Building the Swap Transaction

A swap transaction has two inputs and two outputs. The inputs spend the NFTs to be swapped. The outputs are the NFTs after the swap with their owners exchanged.
A swap transaction has two inputs and two outputs. The inputs spend the NFTs to be swapped. The outputs are the NFTs after the swap with their owners exchanged.

Alice passes an expression containing both the code of the `StaticSwap` class and the expression `StaticSwap.exec(a, b)` to the [`encode`](./API/encode.md) function. The second argument is an environment that determines that the values to be used for `a` and `b` are stored at revisions `a._rev` and `b._rev`.
Alice passes an expression containing both the code of the `StaticSwap` class and the expression `StaticSwap.exec(a, b)` to the [`encode`](../lib/encode.md) function. The second argument is an environment that determines that the values to be used for `a` and `b` are stored at revisions `a._rev` and `b._rev`.

```ts
const { tx } = await alice.encode({
Expand All @@ -67,9 +68,11 @@ const { tx } = await alice.encode({

The `encode` function will automatically sign all inputs of the transaction that can be signed with the private key of the computer object on which the function is called. In this case, this is the input as revision `a._rev`.

The function `encode` will not broadcast automatically. This feature is useful when you want to check the transaction before broadcasting it. It also allows more advanced use cases, for example, using different signature hash types, or signing only specific inputs. More on this in the [API documentation](../lib/encode.md).

### Executing the Swap

Then Bob signs the input `b._rev` and broadcasts the transaction. When the transaction is included in the blockchain the swap is executed and the owners of the two NFTs are reversed.
The transaction created above was partially signed (only Alice's signature was added). Bob now signs the input `b._rev` and broadcasts the transaction. When the transaction is included in the blockchain the swap is executed and the owners of the two NFTs are reversed.

```ts
await bob.sign(tx)
Expand Down Expand Up @@ -104,7 +107,7 @@ await bob.broadcast(tx)

#### Reducing Fees

The disadvantage of the code above is that the swap class is written into the blockchain on every swap. This wasts block space and is expensive. A more efficient approach is to deploy the `Swap` function as a module first and then refer to the module from the transactions executing the swap. To make this easier, we provide a helper class [`SwapHelper`](https://github.com/bitcoin-computer/monorepo/blob/main/packages/swap/src/swap.ts) for swaps and `NftHelper` for NFTs that can be used as follows:
The disadvantage of the code above is that the swap class is written into the blockchain on every swap. This wastes block space and is expensive. A more efficient approach is to deploy the `Swap` function as a module first and then refer to the module from the transactions executing the swap. To make this easier, we provide a helper class [`SwapHelper`](https://github.com/bitcoin-computer/monorepo/blob/main/packages/swap/src/swap.ts) for swaps and `NftHelper` for NFTs that can be used as follows:

```ts
// Alice creates helper objects
Expand Down Expand Up @@ -138,4 +141,4 @@ await alice.broadcast(tx)

## Code

Have a look at the code on [Github](https://github.com/bitcoin-computer/monorepo/tree/main/packages/swap#readme) for details.
Have a look at the code on [Github](https://github.com/bitcoin-computer/monorepo/tree/main/packages/swap#readme) for details.
Loading