diff --git a/pages/framework/card-sdk.mdx b/pages/framework/card-sdk.mdx deleted file mode 100644 index 5163d27..0000000 --- a/pages/framework/card-sdk.mdx +++ /dev/null @@ -1,309 +0,0 @@ -# Card SDK - -The Card SDK provides the glue between the Javascript defined in the TokenScript project and the engine. -It is essentially a 2-way message bus that allows the TokenScript developer to make requests to the engine and to receive updated data and other events emitted by the engine. -It also allows the user to access various data including context data, environment variables & contract information. - -## Token Context Data - -As explained in the introduction to TokenScript attributes, Token Context data is made available through the card SDK. -Our starter templates already handles the dataChange event which is used to provide initial and updated token context data to your card. - -If you want to register your own listener, you can do so by overwriting the following eventHandler - -```typescript -tokenscript.tokens.dataChanged = async (oldTokens: any, updatedTokens: ITokenData, id: string) => { - -} -``` - -For our Svelte & React templates, the `updatedTokens.currentInstance` is automatically written to a global context variable that your UI can react to. - -## Environment Variables - -To access environment variables within your card, ensure that the variables is added into `ts:meta` as demonstrated [here](./tokenscript-syntax/xml). - -You can then access these variables via the `tokenscript.env` object: - -```typescript -tokenscript.env.MY_ENV_VARIABLE -``` - -## Event handlers - -The engine include event handler infrastructure that allows the registration of multiple event listeners throughout your application. - -Currently, there is only one handler however more will be added in the future: - -- TRANSACTION_EVENT - -```typescript -// Types -interface TokenScriptEvents { - TRANSACTION_EVENT: ITransactionStatus -} - -// Usage -tokenscript.on("TRANSACTION_EVENT", (data: ITransactionStatus) => { - // Handle transaction event -}) -``` - -The TRANSACTION_EVENT can be used to react to transaction status even when the default action button is used to trigger the transaction. - -## Bundled libraries - -To reduce the size of built TokenScripts, some common libraries are bundled with the Card SDK. -This allows the use of these libraries without explicitly installing them via NPM. - -Bundled libraries - -- Ethers.js ^v6.13 - available via the `ethers` global variable - -## Engine & UX actions - -### setProps - -One of the most important engine actions is `setProps`. It allows the user to define values that can be used as inputs to attributes & transactions: - -```typescript -tokenscript.action.setProps({ - myAttribute: "123", - myAttribute2: 456 -}) -``` - -When invoking this method, the engine checks these values to see if they are `ts:user-entry` attributes. -If they are not user entry values the engine checks if any of these values are a dependency for another attribute defined in the current scope. -If so the engine will reload those attributes and return the updated data to the card via the `dataChanged` handler explained above. -In this way, attribute values can be updated automatically based on an input that is set programmatically from within the card. - -Likewise, declarative transactions can reference these values as transactions arguments. - -Both attributes & transactions reference these values using the `local-ref` XML attribute: - -```xml - - - - - -``` - -### show/hideLoader - -A self-explanatory method, this allows the user to show or hide the default card loaded provided the TokenScript viewer UI: - -`tokenscript.action.showLoader()` OR `tokenscript.action.hideLoader()`. - -### setActionButton - -The setActionButton method allows the developer to control the state of the default action button: - -```typescript -// Type -type setActionButton = (options: { show?: boolean, disable?: boolean, text?: string }) => void - -// Usage -tokenscript.action.setActionButton({ - show: true, // Whether to show the button - disable: false, // Whether to make the button disabled - text: "Transfer Now" // The text of the button -}) -``` - -This allows the user to hide, disable or update the button text based on some conditions defined in Javascript. - -### executeTransaction - -`executeTransaction` is used to invoke declarative transactions programmatically as discussed in [TokenScript Transactions](./tokenscript-syntax/transactions). - -```typescript -// Types -interface TXOptions { - txName?: string -} - -interface ITransactionStatus { - status: 'started'|'aborted'|'submitted'|'confirmed'|'completed', - txNumber?: string, - txLink?: string, - txRecord?: any -} - -interface ITransactionListener { - (data: ITransactionStatus): void|Promise -} - -type ExecuteTransaction = (optionsOrTxName?: string|TXOptions, listener?: ITransactionListener) => Promise - -// Usage - -// 1. Execute the default transaction (specified in `ts:card`) -if (!await tokenscript.action.executeTransaction()){ - return; // User aborted transaction -} -// Do some post-transaction processing - -// 2. Execute a top-level named transaction, with some input values from Javascript -tokenscript.action.setProps({ - secretCode: "1234" -}); -if (!await tokenscript.action.executeTransaction("levelUp")){ - return; // User aborted transaction -} - -// 3. Use a transaction progress listener -await tokenscript.action.executeTransaction("levelUp", (txInfo) => { - // Update UI based on transaction process -}); - -``` - -Since the executeTransaction method is async, it can be used to chain together transactions and other off-chain processes. - -### showMessageToast - -This allows the developer to show message notifications using the toast notification system provided by TokenScript viewer. -Along with the other UI specific methods, this helps keep the user-experience consistent across all TokenScript applications. - -```typescript -// Type -type ShowMessageToast = (type: 'success'|'info'|'warning'|'error', title: string, description: string) => void; - -// Usage -tokenscript.action.showMessageToast("error", "An error occurred", "Detailed information about the error"); -``` - -### showTransactionToast - -Like the previous method, this allows the user to show transaction specific notifications: - -```typescript -// Type -type ShowTransactionToast = (status: "submitted"|"confirmed", chain: number, txHash: string) => void; - -// Usage -tokenscript.action.showTransactionToast('confirmed', 137, "0x05b9d22ce9ac87e399c18c488c3e02327945ffb4633890030789ea1f2f783e0b"); -``` - -Note: This method only needs to be used when using the injected ethereum provider. If you are using declarative transactions, notifications are already taken care of by the engine. - -### closeCard - -This method simply closes the current card: - -```typescript -tokenscript.action.closeCard(); -``` - -### openCard - -You can also switch between cards using the `openCard` method. - -```typescript -// Type -type OpenCard = (name: string, originId?: string, tokenId?: string) => void; - -// Usage -tokenscript.action.openCard({ - name: "myCardName", - originId: "ReallyCoolToken", // This is the name of the origin contract as defined in the tokenscript.xml. - tokenId: "1" // The tokenId we want to open the card for -}); -``` - -If originId or tokenId are not provided, the current token context is used to open the new card. - -## Ethereum methods - -### Signing - -You can request the user to sign a personal message like this: - -```typescript -// Type -type SignPersonal = (msgParams: {data: string|Uint8Array}, callback?: (error: any, data: string) => void) => void|Promise; - -// Usage -const signature = await tokenscript.personal.sign({data: "My message"}); -``` - -This method is async but can also take a callback as well. - -**Note: If you need typed data signing, use the Ethereum Provider** - -### getRpcUrls - -The `getRpcUrls` method provides an array of RPC URLs for the specified chain ID: - -```typescript -// Type -type GetRpcUrls = (chain: number) => string[]; - -// Usage -const rpcUrls = tokenscript.eth.getRpcUrls(137); -```` - -These URLs are configured and provided by the TokenScript Engine. - -### getRpcProvider - -Instead of requesting URLs and configuring the ethereum provider yourself, you can get an ethers.js provider directly: - -```typescript -// Type -type GetRpcProvider = (chain: number) => AbstractProvider; // ethers.AbstractProvider - -// Usage -const provider = tokenscript.eth.getRpcProvider(137); -``` - -If more than one RPC URL is defined for the specified chain ethers.FallbackProvider is returned, otherwise ethers.JsonRpcProvider is returned. - -### getContractInfo - -It's often helpful to get contract information based on the name specified in the TokenScript XML. -In this way there is no need to hard-code contract addresses and ABI JSON within your Javascript code. -Instead, this config information can be specified within the `tokenscript-project.json` environment variables and made available via this API method. - -```typescript -// Type -type GetContractInfo = (name: string, chain?: number) => {chain: number, address: string, abi: any}; - -// Usage -const contractInfo = tokenscript.eth.getContractInfo("MyReallyCoolToken"); -``` - -If the chain parameter isn't provided, the chain of the current token is used or the first chain specified within `ts:contract`. - -### getContractInstance - -Just like getContractInfo, we can get an ethers.Contract instance based on the name & chain provided. -These contracts must have an ABI specified within `ts:contract` for the methods you want to execute. - -```typescript -// Type -type GetContractInstance = (name: string, chain?: number) => Contract; // ethers.Contract - -// Usage -const contract = tokenscript.eth.getContractInstance("MyReallyCoolToken"); // ABI with getTokenPoints is defined in `ts:contract` -const points = await contract.getTokenPoints(token.tokenId); -``` - -This is most helpful when we want to read contract data within a card, without the use of TokenScript attributes that are loaded when the card is open. - -## Ethereum provider - -To allow scenarios that are not supported by TokenScript's declarative transactions, the Card SDK provides an EIP-1193 proxy. -This is the standard injected provider (`window.ethereum`) that you would be familiar with from integrating with Metamask and other browser extension wallets. - -To use this provider, it's recommended that you wrap it with Ethers.js BrowserProvider like so: -```typescript -const provider = new ethers.BrowserProvider(window.ethereum); - -// You can then get an ethers contract instance to interact with a contract -const contract = new ethers.Contract(contractAddress, abi, provider); -``` - -**Note: When using the injected provider, you must take care of chain switching, transaction notifications & error handling yourself.** \ No newline at end of file diff --git a/pages/framework/card-sdk/_meta.json b/pages/framework/card-sdk/_meta.json new file mode 100644 index 0000000..90a9aad --- /dev/null +++ b/pages/framework/card-sdk/_meta.json @@ -0,0 +1,5 @@ +{ + "introduction": "Introduction", + "engine-actions": "Engine & UI Actions", + "ethereum-methods": "Ethereum Methods" +} diff --git a/pages/framework/card-sdk/engine-actions.mdx b/pages/framework/card-sdk/engine-actions.mdx new file mode 100644 index 0000000..2627ed5 --- /dev/null +++ b/pages/framework/card-sdk/engine-actions.mdx @@ -0,0 +1,154 @@ +## Engine & UX actions + +### setProps + +One of the most important engine actions is `setProps`. It allows the user to define values that can be used as inputs to attributes & transactions: + +```typescript +tokenscript.action.setProps({ + myAttribute: "123", + myAttribute2: 456 +}) +``` + +When invoking this method, the engine checks these values to see if they are `ts:user-entry` attributes. +If they are not user entry values the engine checks if any of these values are a dependency for another attribute defined in the current scope. +If so the engine will reload those attributes and return the updated data to the card via the `dataChanged` handler explained above. +In this way, attribute values can be updated automatically based on an input that is set programmatically from within the card. + +Likewise, declarative transactions can reference these values as transactions arguments. + +Both attributes & transactions reference these values using the `local-ref` XML attribute: + +```xml + + + + + +``` + +### show/hideLoader + +A self-explanatory method, this allows the user to show or hide the default card loaded provided the TokenScript viewer UI: + +`tokenscript.action.showLoader()` OR `tokenscript.action.hideLoader()`. + +### setActionButton + +The setActionButton method allows the developer to control the state of the default action button: + +```typescript +// Type +type setActionButton = (options: { show?: boolean, disable?: boolean, text?: string }) => void + +// Usage +tokenscript.action.setActionButton({ + show: true, // Whether to show the button + disable: false, // Whether to make the button disabled + text: "Transfer Now" // The text of the button +}) +``` + +This allows the user to hide, disable or update the button text based on some conditions defined in Javascript. + +### executeTransaction + +`executeTransaction` is used to invoke declarative transactions programmatically as discussed in [TokenScript Transactions](./tokenscript-syntax/transactions). + +```typescript +// Types +interface TXOptions { + txName?: string +} + +interface ITransactionStatus { + status: 'started'|'aborted'|'submitted'|'confirmed'|'completed', + txNumber?: string, + txLink?: string, + txRecord?: any +} + +interface ITransactionListener { + (data: ITransactionStatus): void|Promise +} + +type ExecuteTransaction = (optionsOrTxName?: string|TXOptions, listener?: ITransactionListener) => Promise + +// Usage + +// 1. Execute the default transaction (specified in `ts:card`) +if (!await tokenscript.action.executeTransaction()){ + return; // User aborted transaction +} +// Do some post-transaction processing + +// 2. Execute a top-level named transaction, with some input values from Javascript +tokenscript.action.setProps({ + secretCode: "1234" +}); +if (!await tokenscript.action.executeTransaction("levelUp")){ + return; // User aborted transaction +} + +// 3. Use a transaction progress listener +await tokenscript.action.executeTransaction("levelUp", (txInfo) => { + // Update UI based on transaction process +}); + +``` + +Since the executeTransaction method is async, it can be used to chain together transactions and other off-chain processes. + +### showMessageToast + +This allows the developer to show message notifications using the toast notification system provided by TokenScript viewer. +Along with the other UI specific methods, this helps keep the user-experience consistent across all TokenScript applications. + +```typescript +// Type +type ShowMessageToast = (type: 'success'|'info'|'warning'|'error', title: string, description: string) => void; + +// Usage +tokenscript.action.showMessageToast("error", "An error occurred", "Detailed information about the error"); +``` + +### showTransactionToast + +Like the previous method, this allows the user to show transaction specific notifications: + +```typescript +// Type +type ShowTransactionToast = (status: "submitted"|"confirmed", chain: number, txHash: string) => void; + +// Usage +tokenscript.action.showTransactionToast('confirmed', 137, "0x05b9d22ce9ac87e399c18c488c3e02327945ffb4633890030789ea1f2f783e0b"); +``` + +Note: This method only needs to be used when using the injected ethereum provider. If you are using declarative transactions, notifications are already taken care of by the engine. + +### closeCard + +This method simply closes the current card: + +```typescript +tokenscript.action.closeCard(); +``` + +### openCard + +You can also switch between cards using the `openCard` method. + +```typescript +// Type +type OpenCard = (name: string, originId?: string, tokenId?: string) => void; + +// Usage +tokenscript.action.openCard({ + name: "myCardName", + originId: "ReallyCoolToken", // This is the name of the origin contract as defined in the tokenscript.xml. + tokenId: "1" // The tokenId we want to open the card for +}); +``` + +If originId or tokenId are not provided, the current token context is used to open the new card. diff --git a/pages/framework/card-sdk/ethereum-methods.mdx b/pages/framework/card-sdk/ethereum-methods.mdx new file mode 100644 index 0000000..da1412d --- /dev/null +++ b/pages/framework/card-sdk/ethereum-methods.mdx @@ -0,0 +1,92 @@ +## Ethereum methods + +### Signing + +You can request the user to sign a personal message like this: + +```typescript +// Type +type SignPersonal = (msgParams: {data: string|Uint8Array}, callback?: (error: any, data: string) => void) => void|Promise; + +// Usage +const signature = await tokenscript.personal.sign({data: "My message"}); +``` + +This method is async but can also take a callback as well. + +**Note: If you need typed data signing, use the Ethereum Provider** + +### getRpcUrls + +The `getRpcUrls` method provides an array of RPC URLs for the specified chain ID: + +```typescript +// Type +type GetRpcUrls = (chain: number) => string[]; + +// Usage +const rpcUrls = tokenscript.eth.getRpcUrls(137); +```` + +These URLs are configured and provided by the TokenScript Engine. + +### getRpcProvider + +Instead of requesting URLs and configuring the ethereum provider yourself, you can get an ethers.js provider directly: + +```typescript +// Type +type GetRpcProvider = (chain: number) => AbstractProvider; // ethers.AbstractProvider + +// Usage +const provider = tokenscript.eth.getRpcProvider(137); +``` + +If more than one RPC URL is defined for the specified chain ethers.FallbackProvider is returned, otherwise ethers.JsonRpcProvider is returned. + +### getContractInfo + +It's often helpful to get contract information based on the name specified in the TokenScript XML. +In this way there is no need to hard-code contract addresses and ABI JSON within your Javascript code. +Instead, this config information can be specified within the `tokenscript-project.json` environment variables and made available via this API method. + +```typescript +// Type +type GetContractInfo = (name: string, chain?: number) => {chain: number, address: string, abi: any}; + +// Usage +const contractInfo = tokenscript.eth.getContractInfo("MyReallyCoolToken"); +``` + +If the chain parameter isn't provided, the chain of the current token is used or the first chain specified within `ts:contract`. + +### getContractInstance + +Just like getContractInfo, we can get an ethers.Contract instance based on the name & chain provided. +These contracts must have an ABI specified within `ts:contract` for the methods you want to execute. + +```typescript +// Type +type GetContractInstance = (name: string, chain?: number) => Contract; // ethers.Contract + +// Usage +const contract = tokenscript.eth.getContractInstance("MyReallyCoolToken"); // ABI with getTokenPoints is defined in `ts:contract` +const points = await contract.getTokenPoints(token.tokenId); +``` + +This is most helpful when we want to read contract data within a card, without the use of TokenScript attributes that are loaded when the card is open. + +## Ethereum provider + +To allow scenarios that are not supported by TokenScript's declarative transactions, the Card SDK provides an EIP-1193 proxy. +This is the standard injected provider (`window.ethereum`) that you would be familiar with from integrating with Metamask and other browser extension wallets. + +To use this provider, it's recommended that you wrap it with Ethers.js BrowserProvider like so: +```typescript +const provider = new ethers.BrowserProvider(window.ethereum); + +// You can then get an ethers contract instance to interact with a contract +const contract = new ethers.Contract(contractAddress, abi, provider); +``` + +**Note: When using the injected provider, you must take care of chain switching, transaction notifications & error handling yourself.** \ No newline at end of file diff --git a/pages/framework/card-sdk/introduction.mdx b/pages/framework/card-sdk/introduction.mdx new file mode 100644 index 0000000..3ca3942 --- /dev/null +++ b/pages/framework/card-sdk/introduction.mdx @@ -0,0 +1,61 @@ +# Card SDK + +The Card SDK provides the glue between the Javascript defined in the TokenScript project and the engine. +It is essentially a 2-way message bus that allows the TokenScript developer to make requests to the engine and to receive updated data and other events emitted by the engine. +It also allows the user to access various data including context data, environment variables & contract information. + +## Token Context Data + +As explained in the introduction to TokenScript attributes, Token Context data is made available through the card SDK. +Our starter templates already handles the dataChange event which is used to provide initial and updated token context data to your card. + +If you want to register your own listener, you can do so by overwriting the following eventHandler + +```typescript +tokenscript.tokens.dataChanged = async (oldTokens: any, updatedTokens: ITokenData, id: string) => { + +} +``` + +For our Svelte & React templates, the `updatedTokens.currentInstance` is automatically written to a global context variable that your UI can react to. + +## Environment Variables + +To access environment variables within your card, ensure that the variables is added into `ts:meta` as demonstrated [here](./tokenscript-syntax/xml). + +You can then access these variables via the `tokenscript.env` object: + +```typescript +tokenscript.env.MY_ENV_VARIABLE +``` + +## Event handlers + +The engine include event handler infrastructure that allows the registration of multiple event listeners throughout your application. + +Currently, there is only one handler however more will be added in the future: + +- TRANSACTION_EVENT + +```typescript +// Types +interface TokenScriptEvents { + TRANSACTION_EVENT: ITransactionStatus +} + +// Usage +tokenscript.on("TRANSACTION_EVENT", (data: ITransactionStatus) => { + // Handle transaction event +}) +``` + +The TRANSACTION_EVENT can be used to react to transaction status even when the default action button is used to trigger the transaction. + +## Bundled libraries + +To reduce the size of built TokenScripts, some common libraries are bundled with the Card SDK. +This allows the use of these libraries without explicitly installing them via NPM. + +Bundled libraries + +- Ethers.js ^v6.13 - available via the `ethers` global variable