{"id":21082751,"url":"https://github.com/renproject/ren-tx","last_synced_at":"2025-03-14T04:43:58.268Z","repository":{"id":45884375,"uuid":"413574024","full_name":"renproject/ren-tx","owner":"renproject","description":"RenVM transaction state management library","archived":false,"fork":false,"pushed_at":"2021-11-30T02:24:48.000Z","size":835,"stargazers_count":1,"open_issues_count":3,"forks_count":2,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-01-20T23:46:54.767Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/renproject.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-10-04T20:30:12.000Z","updated_at":"2022-02-28T03:56:47.000Z","dependencies_parsed_at":"2022-09-05T08:11:20.000Z","dependency_job_id":null,"html_url":"https://github.com/renproject/ren-tx","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/renproject%2Fren-tx","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/renproject%2Fren-tx/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/renproject%2Fren-tx/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/renproject%2Fren-tx/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/renproject","download_url":"https://codeload.github.com/renproject/ren-tx/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243526855,"owners_count":20305112,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-19T20:15:12.601Z","updated_at":"2025-03-14T04:43:58.245Z","avatar_url":"https://github.com/renproject.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# `🤖 @renproject/ren-tx`\n\nThis implements RenVM transaction lifecycles in [xstate](https://xstate.js.org) state-machines to allow developers to easily trace the state of a transaction, and explicitly know which cases they should handle during processing.\n\nThe aim is to provide a declarative interface, that can accept serializable \"transaction\" objects, that will reactively process the appropriate stages in the transaction lifecycle.\n\n## Differences between RenJS and @renproject/ren-tx\n\n|                           | renjs | @renproject/ren-tx |\n| ------------------------- | ----- | ------------------ |\n| reactive                  | ❌    | ✓                  |\n| serializable transactions | ❌    | ✓                  |\n| finite, explicit states   | ❌    | ✓                  |\n\n## Concepts\n\nIn order to make full use of this library, it is valuable to understand the [concepts behind xstate](https://xstate.js.org/docs/about/concepts.html#finite-state-machines)\n\nAt a high level, this package provides\n\n-   `mintMachine` - a machine for instantiating a gateway address and listening for deposits.\n-   `depositMachine` - a machine for processing the lifecycle of a gateway deposit, all the way from detection on the source chain, until confirmation on the destination chain.\n-   `burnMachine` - a machine for processing burn and release transactions.\n\nAs well as a standard serializable schema for persisting and restoring transactions, `GatewaySession`\n\n## Usage\n\nIn order to mint or burn, all the developer needs to do is to import the appropriate machine for for the desired flow, provide the necessary dependencies via the machine context, and run the machine via the appropriate interpreter for their application (eg `@xstate/react` for `react` applications).\n\nEach machine requires\n\n-   `tx` - transaction parameters\n-   `sdk` - the `RenJS` sdk instantiated for the appropriate network\n-   `providers` - Blockchain wallet providers for signing and sending transactions for desired networks\n-   `fromChainMap` - A mapping of source networks to builders for their `@renproject/chains` parameters\n-   `toChainMap` - A mapping of destination networks to builders for their `@renproject/chains` parameters\n\n### Standalone xstate example\n\n(see the `/demos` folder for complete examples)\n\n#### Minting\n\n```typescript\nimport { interpret } from \"xstate\";\nimport {\n    mintMachine,\n    mintConfig,\n    GatewaySession,\n    GatewayMachineContext,\n} from \"../\"; //\"@renproject/rentx\";\nimport RenJS from \"@renproject/ren\";\nimport { BinanceSmartChain, Ethereum } from \"@renproject/chains-ethereum\";\nimport { Bitcoin, BitcoinCash, Zcash } from \"@renproject/chains-bitcoin\";\nimport HDWalletProvider from \"@truffle/hdwallet-provider\";\nimport ethers from \"ethers\";\n\nconst MNEMONIC = process.env.MNEMONIC;\nconst INFURA_URL = process.env.INFURA_URL;\nconst hdWalletProvider = new HDWalletProvider({\n    mnemonic: MNEMONIC || \"\",\n    providerOrUrl: infuraURL,\n    addressIndex: 0,\n    numberOfAddresses: 10,\n});\nconst ethProvider = new ethers.providers.Web3Provider(hdWalletProvider);\n\nconst mintTransaction: GatewaySession = {\n    id: \"a unique identifier\",\n    type: \"mint\",\n    network: \"testnet\",\n    sourceAsset: \"btc\",\n    sourceChain: \"bitcoin\",\n    destAddress: \"ethereum address that will receive assets\",\n    destChain: \"ethereum\",\n    targetAmount: 0.001,\n    userAddress: \"address that will sign the transaction\",\n    expiryTime: new Date().getTime() + 1000 * 60 * 60 * 24,\n    transactions: {},\n    customParams: {},\n};\n\n// A mapping of how to construct parameters for host chains,\n// based on the destination network\nexport const toChainMap = {\n    binanceSmartChain: (context: GatewayMachineContext) =\u003e {\n        const { destAddress, destChain, network } = context.tx;\n        const { providers } = context;\n        return new BinanceSmartChain(providers[destChain], network).Account({\n            address: destAddress,\n        });\n    },\n    ethereum: (context: GatewayMachineContext) =\u003e {\n        const { destAddress, destChain, network } = context.tx;\n        const { providers } = context;\n\n        return Ethereum(providers[destChain], network).Account({\n            address: destAddress,\n        });\n    },\n};\n\n// A mapping of how to construct parameters for source chains,\n// based on the source network\nexport const fromChainMap = {\n    bitcoin: () =\u003e Bitcoin(),\n    zcash: () =\u003e Zcash(),\n    bitcoinCash: () =\u003e BitcoinCash(),\n};\n\nconst blockchainProviders = {\n    ethereum: hdWalletProvider,\n};\n\nethProvider.listAccounts().then((accounts) =\u003e {\n    mintTransaction.destAddress = accounts[0];\n    mintTransaction.userAddress = accounts[0];\n    const machine = mintMachine.withConfig(mintConfig).withContext({\n        tx: mintTransaction,\n        sdk: new RenJS(\"testnet\"),\n        providers: blockchainProviders,\n        fromChainMap,\n        toChainMap,\n    });\n\n    // Interpret the machine, and add a listener for whenever a transition occurs.\n    // The machine will detect which state the transaction should be in,\n    // and perform the neccessary next actions\n    let promptedGatewayAddress = false;\n    let claimed = false;\n    const service = interpret(machine).onTransition((state) =\u003e {\n        if (!promptedGatewayAddress \u0026\u0026 state.context.tx.gatewayAddress) {\n            console.log(\n                \"Please deposit BTC to\",\n                state.context.tx.gatewayAddress,\n            );\n            promptedGatewayAddress = true;\n        }\n        const deposit = Object.values(state.context.tx.transactions || {})[0];\n        if (\n            state.context.mintRequests.includes(deposit.sourceTxHash) \u0026\u0026\n            !claimed\n        ) {\n            // implement logic to determine whether deposit is valid\n            // In our case we take the first deposit to be the correct one\n            // and immediately sign\n            console.log(\"Signing transaction\");\n            claimed;\n            service.send({ type: \"CLAIM\", hash: deposit.sourceTxHash });\n        }\n        if (deposit \u0026\u0026 deposit.destTxHash) {\n            // If we have a destination txHash, we have successfully minted BTC\n            console.log(\"Your BTC has been minted! TxHash\", deposit.destTxHash);\n            service.stop();\n        }\n    });\n\n    // Start the service\n    service.start();\n});\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frenproject%2Fren-tx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frenproject%2Fren-tx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frenproject%2Fren-tx/lists"}