diff --git a/website/docs/releases/release-notes.md b/website/docs/releases/release-notes.md index cb35740b..26bd0930 100644 --- a/website/docs/releases/release-notes.md +++ b/website/docs/releases/release-notes.md @@ -24,6 +24,10 @@ title: Release Notes - :hammer_and_wrench: Improve libauth template generation. - :bug: Fix bug where `SignatureTemplate` would not accept private key hex strings as a signer. +--- + +https://x.com/CashScriptBCH/status/1973692336782876974 + ## v0.11.5 #### CashScript SDK diff --git a/website/docs/sdk/electrum-network-provider.md b/website/docs/sdk/electrum-network-provider.md index bf216424..80a52766 100644 --- a/website/docs/sdk/electrum-network-provider.md +++ b/website/docs/sdk/electrum-network-provider.md @@ -2,11 +2,17 @@ title: Electrum Network Provider --- -The CashScript SDK needs to connect to the BCH network to perform certain operations, like retrieving the contract's balance, or sending transactions. By default the network provider is an `ElectrumNetworkProvider`. +The CashScript SDK needs to connect to the BCH network to perform certain operations, like retrieving the contract's balance, or sending transactions. The recommended network provider is the `ElectrumNetworkProvider`. -## ElectrumNetworkProvider +## Creating an ElectrumNetworkProvider -The ElectrumNetworkProvider uses [@electrum-cash/network][electrum-cash] to connect to the BCH network. Both `network` and `options` parameters are optional, and they default to mainnet with the `bch.imaginary.cash` electrum server. +The ElectrumNetworkProvider uses [@electrum-cash/network][electrum-cash] library to connect to the configured electrum server. The connection uses a single, trusted electrum server so it does no have any fallback logic and does not validate SPV proofs for chain inclusion. + +By default the `ElectrumNetworkProvider` creates a short-lived connection only when requests are pending. To configure this see the section on '[Manual Connection Management](#manual-connection-management)'. + +### Constructor + +Both `network` and `options` parameters are optional, and they default to `mainnet` with the `bch.imaginary.cash` electrum server. ```ts new ElectrumNetworkProvider(network?: Network, options?: Options) @@ -44,6 +50,9 @@ const hostname = 'chipnet.bch.ninja'; const provider = new ElectrumNetworkProvider('chipnet', { hostname }); ``` +## ElectrumNetworkProvider Methods + + ### getUtxos() ```ts async provider.getUtxos(address: string): Promise; @@ -143,5 +152,27 @@ provider.disconnect(): Promise; Disconnects from the electrum client, returns `true` if the client was connected, `false` if it was already disconnected. +## Using electrum-cash functionality + +To use more of the electrum-specific functionality which is not exposed in the `ElectrumNetworkProvider` you can simply call the methods on the electrum Client itself. + +### Custom Electrum Client + +When initializing an `ElectrumNetworkProvider` you have the option in the constructor to provide a custom electrum client. This way you can use one and the same indexer server for blockchain information but use it through two different interfaces. This allows you to access all underlying functionality of the [@electrum-cash/network][electrum-cash] library like address and blockHeight subscriptions. + +If intending to use electrum-cash subscriptions, make sure to set `manualConnectionManagement` to true, so the `ElectrumNetworkProvider` does not disconnect after each request. + +#### example + +```ts +import { ElectrumClient } from '@electrum-cash/network'; +import { ElectrumNetworkProvider } from 'cashscript'; + +const electrum = new ElectrumClient('CashScript Application', '1.4.1', 'chipnet.bch.ninja'); +const provider = new ElectrumNetworkProvider(Network.CHIPNET, { + electrum, manualConnectionManagement: true +}); +await electrum.connect(); +``` [electrum-cash]: https://www.npmjs.com/package/@electrum-cash/network diff --git a/website/docs/sdk/instantiation.md b/website/docs/sdk/instantiation.md index 275b66f7..9adcc3dc 100644 --- a/website/docs/sdk/instantiation.md +++ b/website/docs/sdk/instantiation.md @@ -4,11 +4,6 @@ title: Contract Instantiation Before interacting with a smart contract on the BCH network, the CashScript SDK needs to instantiate a `Contract` object. This is done by providing the contract's information and constructor arguments. After this instantiation, the CashScript SDK can interact with the BCH contract. -:::info -CashScript offers a TypeScript SDK, which can also be used easily in vanilla JavaScript codebases. -Because of the separation of the compiler and the SDK, CashScript contracts can be integrated into other languages in the future. -::: - ## Creating a Contract The `Contract` class is used to represent a CashScript contract in a JavaScript object. These objects can be used to retrieve information such as the contract's address and balance. Contract objects can be used to interact with the contract by generating an `Unlocker` by calling the contract's unlocker functions. @@ -17,16 +12,20 @@ The `Contract` class is used to represent a CashScript contract in a JavaScript new Contract( artifact: Artifact, constructorArgs: ConstructorArgument[], - options? : { + options : { provider: NetworkProvider, - addressType: 'p2sh20' | 'p2sh32', + addressType?: 'p2sh20' | 'p2sh32', } ) ``` A CashScript contract can be instantiated by providing an `Artifact` object, a list of constructor arguments, and optionally an options object configuring `NetworkProvider` and `addressType`. -An `Artifact` object is the result of compiling a CashScript contract. Compilation can be done using the standalone [`cashc` CLI](/docs/compiler) or programmatically with the `cashc` NPM package (see [CashScript Compiler](/docs/compiler#javascript-compilation)). If compilation is done using the `cashc` CLI with the `--format ts` option, you will get explicit types and type checking for the constructor arguments and function arguments. +An `Artifact` object is the result of compiling a CashScript contract. Compilation can be done using the standalone [`cashc` CLI](/docs/compiler) or programmatically with the `cashc` NPM package (see [CashScript Compiler](/docs/compiler#javascript-compilation)). + +:::tip +If compilation is done using the `cashc` CLI with the `--format ts` option to output TypeScript Artifacts, you will get explicit types and type checking for the constructor arguments and function arguments of the `Contract` class. +::: The `NetworkProvider` option is used to manage network operations for the CashScript contract. By default, a mainnet `ElectrumNetworkProvider` is used, but the network providers can be configured. See the docs on [NetworkProvider](/docs/sdk/network-provider). @@ -170,6 +169,10 @@ contract.unlock.(...args: FunctionArgument[]): Unlocker Once a smart contract has been instantiated, you can invoke a contract function on a smart contract UTXO to use the '[Transaction Builder](/docs/sdk/transaction-builder)' by calling the function name under the `unlock` member field of a contract object. To call these functions successfully, the provided parameters must match the function signature defined in the CashScript code. +:::tip +When using a TypeScript contract Artifact, you will get explicit types and type checking for the function name and arguments. +::: + These contract functions return an incomplete `transactionBuilder` object, which needs to be completed by providing outputs of the transaction. For more information see the [transaction-builder](/docs/sdk/transaction-builder) page. ```ts @@ -180,6 +183,3 @@ const contractUtxos = await contract.getUtxos(); transactionBuilder.addInput(contractUtxos[0], contract.unlock.spend()); ``` -:::tip -If the contract artifact is generated using the `cashc` CLI with the `--format ts` option, you will get explicit types and type checking for the function name and arguments. -::: diff --git a/website/docs/sdk/network-provider.md b/website/docs/sdk/network-provider.md index 72e32029..4110ef7b 100644 --- a/website/docs/sdk/network-provider.md +++ b/website/docs/sdk/network-provider.md @@ -2,7 +2,7 @@ title: Network Provider --- -The CashScript SDK needs to connect to the BCH network to perform certain operations, like retrieving the contract's balance, or sending transactions. By default the network provider is an `ElectrumNetworkProvider`, however for local development it is recommended to use a `MockNetworkProvider`. +The CashScript SDK needs to connect to the BCH network to perform certain operations, like retrieving the contract's balance, or sending transactions. The recommended network provider to use blockchain network functionality is the `ElectrumNetworkProvider`, however for local development it is recommended to use a `MockNetworkProvider`. :::tip CashScript NetworkProviders have a standardized interface, this allows different network providers to be used by the SDK and makes it easy to swap out dependencies. @@ -90,3 +90,13 @@ const txId = await provider.sendRawTransaction(txHex) A big strength of the NetworkProvider setup is that it allows you to implement custom providers. So if you want to use a new or different BCH indexer for network information, it is simple to add support for it by creating your own `NetworkProvider` adapter by implementing the [NetworkProvider interface](https://github.com/CashScript/cashscript/blob/master/packages/cashscript/src/network/NetworkProvider.ts). You can create a PR to add your custom `NetworkProvider` to the CashScript codebase to share this functionality with others. It is required to have basic automated tests for any new `NetworkProvider`. + +## Provider-Specific functionality + +Beyond the standardized `NetworkProvider` interface each provider can have its own provider-specific functionality. This can either be done by extending the `NetworkProvider` interface or by providing a more full-featured networking client to create the `NetworkProvider`. + +## Limitations + +If you look at the [Transaction Lifecycle](guides/lifecycle.md) guide then you'll see there are blockchain edge cases like chain re-organisations or double spends. Ideally the `NetworkProvider` interface would be able to provide more detailed `Utxo` chain information like whether the UTXO is unconfirmed or confirmed, the number of confirmations and the block-hash of the block which included the transaction creating the UTXO. + +Currently however the `NetworkProvider` interface does not include the details needed to understand whether blockchain state is confirmed, pending or ended up getting reversed. This means that in the case something does end up being reversed your application might not correctly be in sync with the actual network state. diff --git a/website/docs/sdk/other-network-providers.md b/website/docs/sdk/other-network-providers.md index 85429d98..a853a6bd 100644 --- a/website/docs/sdk/other-network-providers.md +++ b/website/docs/sdk/other-network-providers.md @@ -6,7 +6,7 @@ The CashScript SDK needs to connect to the BCH network to perform certain operat ## MockNetworkProvider ```ts -new MockNetworkProvider(options?: { updateUtxoSet: boolean }) +new MockNetworkProvider(options?: MockNetworkProviderOptions) ``` The `MockNetworkProvider` is a special network provider that allows you to evaluate transactions locally without interacting with the Bitcoin Cash network. This is useful when writing automated tests for your contracts, or when debugging your contract locally. @@ -14,8 +14,17 @@ The `MockNetworkProvider` is a special network provider that allows you to evalu The `MockNetworkProvider` has extra methods to enable this local emulation such as `.addUtxo()` and `.setBlockHeight()`. You can read more about the `MockNetworkProvider` and automated tests on the [testing setup](/docs/sdk/testing-setup) page. +```ts +interface MockNetworkProviderOptions { + updateUtxoSet?: boolean; + vmTarget?: VmTarget; +} +``` + The `updateUtxoSet` option is used to determine whether the UTXO set should be updated after a transaction is sent. If `updateUtxoSet` is `true` (default), the UTXO set will be updated to reflect the new state of the mock network. If `updateUtxoSet` is `false`, the UTXO set will not be updated. +The `vmTarget` option defaults to the current VM of `BCH_2025_05`, but this can be changed to test your contract against different BCH virtual machine targets. + #### Example ```ts const provider = new MockNetworkProvider(); @@ -63,7 +72,7 @@ new BitcoinRpcNetworkProvider(network: Network, url: string, options?: any) The `BitcoinRpcNetworkProvider` uses a direct connection to a BCH node. Note that a regular node does not have indexing, so any address of interest (e.g. the contract address) need to be registered by the node *before* sending any funds to those addresses. Because of this it is recommended to use a different network provider unless you have a specific reason to use the RPC provider. :::caution -The `BitcoinRpcNetworkProvider` does not currently support CashTokens. If you want to use CashTokens, please use the `ElectrumNetworkProvider` instead. +The `BitcoinRpcNetworkProvider` does not currently support CashTokens. If you want to use CashTokens, use the `ElectrumNetworkProvider` instead. ::: #### Example diff --git a/website/docs/sdk/transaction-builder.md b/website/docs/sdk/transaction-builder.md index 4e0d88e3..3ac07fb4 100644 --- a/website/docs/sdk/transaction-builder.md +++ b/website/docs/sdk/transaction-builder.md @@ -20,6 +20,7 @@ interface TransactionBuilderOptions { provider: NetworkProvider; maximumFeeSatoshis?: bigint; maximumFeeSatsPerByte?: number; + allowImplicitFungibleTokenBurn?: boolean; } ``` diff --git a/website/docs/sdk/transactions.md b/website/docs/sdk/transactions.md index 5b2ca52d..3d52400f 100644 --- a/website/docs/sdk/transactions.md +++ b/website/docs/sdk/transactions.md @@ -265,7 +265,7 @@ It is unsafe to debug transactions on mainnet using the BitAuth IDE as private k transaction.getVmResourceUsage(verbose: boolean = false): Array ``` -The `getVmResourceUsage()` function allows you to get the VM resource usage for the transaction. This can be useful for debugging and optimization. +The `getVmResourceUsage()` function allows you to get the VM resource usage for the transaction. This can be useful for debugging and optimization. The VM resource usage is calculated for each input individually so the result is an array of `VmResourceUsage` results corresponding to each of the transaction inputs. ```ts interface VmResourceUsage { @@ -281,7 +281,7 @@ interface VmResourceUsage { } ``` -The verbose mode logs the VM resource usage for each input to the console. +The verbose mode also logs the VM resource usage for each input as a table to the console. ``` VM Resource usage by inputs: diff --git a/website/docs/sdk/typescript-sdk.md b/website/docs/sdk/typescript-sdk.md new file mode 100644 index 00000000..1245356f --- /dev/null +++ b/website/docs/sdk/typescript-sdk.md @@ -0,0 +1,81 @@ +--- +title: TypeScript SDK +--- + +CashScript offers a TypeScript SDK, which makes it easy to build smart contract transactions, both in browser or on the server. By offering full type-safety, developers can be confident in the quality and reliability of their applications. The SDK can also be used easily in vanilla JavaScript codebases, although the benefits of the type-safety will be lost. + +:::info +Because of the separation of the compiler and the SDK, CashScript contracts can be integrated into other programming languages in the future. +::: + +## SDK Classes + +The CashScript SDK consists of 4 classes, together they form one cohesive structure to build BCH smart contract applications. +The documentation also follows the structure of these 4 classes: + +- the `Contract` class +- the `TransactionBuilder` class +- the `NetworkProvider` class +- the `SignatureTemplate` class + +## SDK usage + +The usage of the 4 classes in your code is as follows: before using the SDK you create one or multiple contract artifacts compiled by `cashc`. Then to start using the SDK, you instantiate a `NetworkProvider`, which you then provide to instantiate a `Contract` from an `Artifact`. Once you have a `Contract` instance, you can use it in the `TransactionBuilder`. During transaction building you might need to generate a signature, in which case you would instantiate a `SignatureTemplate`. + +For an more complete example of the SDK flow, refer to the [SDK Example](./examples.md). + +#### example + +```ts +import { Contract, ElectrumNetworkProvider, TransactionBuilder, SignatureTemplate } from 'cashscript'; +import { P2pkhArtifact } from './artifact'; +import { contractArguments, aliceWif } from './somewhere'; + +const provider = new ElectrumNetworkProvider('chipnet'); + +const contract = new Contract(P2pkhArtifact, contractArguments, { provider }); + +const aliceSignatureTemplate = new SignatureTemplate(aliceWif); +const unlocker = contract.unlock.transfer(aliceSignatureTemplate) + +const transactionBuilder = new TransactionBuilder({ provider }); + +// then use the transactionBuilder to actually spend a UTXO with the contract unlocker +``` + +## Full TypeScript Integration + +The constructor of the `Contract` class takes in an `Artifact`, this is the output of the `cashc` compiler and can be configured to either output a JSON or TS file. To have the best TypeScript integration, we recommend generating the artifact in the `.ts` format and importing it into your TypeScript project from that `.ts` file. The type benefits are explained in more details in the documentation for the [Contract](./instantiation#constructor) class. + +## Advanced: non-CashScript Contracts + +You can also use the CashScript SDK without relying on the CashScript contract language and compiler. This way you can still leverage the a lot of the tooling while having full control over the raw BCH script so this can be hand-written or hand-optimized. + +There's two ways to go about this, either you create a custom `Artifact` so you can still use the `Contract` class or you create a custom `Unlocker` to use in the transaction building directly. + +### Custom Artifacts + +You can create an Artifact for a fully hand-written contract so it becomes possible to use the contract with the nice features of the CashScript SDK! An example of this is [Cauldron_Swap_Test](https://github.com/mr-zwets/Cauldron_Swap_Test) which uses `Artifact bytecode` not produced by `cashc` at all but still uses the CashScript SDK. + +### Custom Unlockers + +In the [addInput() method](./transaction-builder#addInput()) on the TransactionBuilder you can provide a custom `Unlocker` + +```ts +transactionBuilder.addInput(utxo: Utxo, unlocker: Unlocker, options?: InputOptions): this +``` + +the `Unlocker` interface is the following: + +```ts +interface Unlocker { + generateLockingBytecode: () => Uint8Array; + generateUnlockingBytecode: (options: GenerateUnlockingBytecodeOptions) => Uint8Array; +} + +interface GenerateUnlockingBytecodeOptions { + transaction: Transaction; + sourceOutputs: LibauthOutput[]; + inputIndex: number; +} +``` diff --git a/website/sidebars.ts b/website/sidebars.ts index a5af5c50..1ffdd947 100644 --- a/website/sidebars.ts +++ b/website/sidebars.ts @@ -37,6 +37,7 @@ const sidebars: SidebarsConfig = { type: 'category', label: 'TypeScript SDK', items: [ + 'sdk/typescript-sdk', 'sdk/instantiation', 'sdk/transaction-builder', {