@geeqdev/geeq-sdk 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.idea/geeq_sdk.iml +12 -0
- package/.idea/modules.xml +8 -0
- package/.idea/vcs.xml +6 -0
- package/.nvmrc +1 -0
- package/CONTRIBUTING.md +20 -0
- package/dist/src/address/record-type.d.ts +10 -0
- package/dist/src/address/record-type.js +59 -0
- package/dist/src/address/record-type.js.map +1 -0
- package/dist/src/address/wallet-address.d.ts +34 -0
- package/dist/src/address/wallet-address.js +90 -0
- package/dist/src/address/wallet-address.js.map +1 -0
- package/dist/src/amount.d.ts +43 -0
- package/dist/src/amount.js +105 -0
- package/dist/src/amount.js.map +1 -0
- package/dist/src/assert.d.ts +12 -0
- package/dist/src/assert.js +24 -0
- package/dist/src/assert.js.map +1 -0
- package/dist/src/capnp/adminNetTx.capnp.d.ts +75 -0
- package/dist/src/capnp/adminNetTx.capnp.js +66 -0
- package/dist/src/capnp/adminNetTx.capnp.js.map +1 -0
- package/dist/src/capnp/appLayBlock.capnp.d.ts +26 -0
- package/dist/src/capnp/appLayBlock.capnp.js +24 -0
- package/dist/src/capnp/appLayBlock.capnp.js.map +1 -0
- package/dist/src/capnp/appLayLedger.capnp.d.ts +34 -0
- package/dist/src/capnp/appLayLedger.capnp.js +32 -0
- package/dist/src/capnp/appLayLedger.capnp.js.map +1 -0
- package/dist/src/capnp/appLayRec.capnp.d.ts +129 -0
- package/dist/src/capnp/appLayRec.capnp.js +156 -0
- package/dist/src/capnp/appLayRec.capnp.js.map +1 -0
- package/dist/src/capnp/chainStateView.capnp.d.ts +50 -0
- package/dist/src/capnp/chainStateView.capnp.js +48 -0
- package/dist/src/capnp/chainStateView.capnp.js.map +1 -0
- package/dist/src/capnp/coinAcctRec.capnp.d.ts +178 -0
- package/dist/src/capnp/coinAcctRec.capnp.js +189 -0
- package/dist/src/capnp/coinAcctRec.capnp.js.map +1 -0
- package/dist/src/capnp/genesisBlock.capnp.d.ts +61 -0
- package/dist/src/capnp/genesisBlock.capnp.js +55 -0
- package/dist/src/capnp/genesisBlock.capnp.js.map +1 -0
- package/dist/src/capnp/hubContentStmt.capnp.d.ts +63 -0
- package/dist/src/capnp/hubContentStmt.capnp.js +57 -0
- package/dist/src/capnp/hubContentStmt.capnp.js.map +1 -0
- package/dist/src/capnp/misc.capnp.d.ts +20 -0
- package/dist/src/capnp/misc.capnp.js +18 -0
- package/dist/src/capnp/misc.capnp.js.map +1 -0
- package/dist/src/capnp/netActorRec.capnp.d.ts +65 -0
- package/dist/src/capnp/netActorRec.capnp.js +65 -0
- package/dist/src/capnp/netActorRec.capnp.js.map +1 -0
- package/dist/src/capnp/nodeContentStmt.capnp.d.ts +67 -0
- package/dist/src/capnp/nodeContentStmt.capnp.js +61 -0
- package/dist/src/capnp/nodeContentStmt.capnp.js.map +1 -0
- package/dist/src/capnp/nodePayloadList.capnp.d.ts +28 -0
- package/dist/src/capnp/nodePayloadList.capnp.js +26 -0
- package/dist/src/capnp/nodePayloadList.capnp.js.map +1 -0
- package/dist/src/capnp/nodeTxList.capnp.d.ts +36 -0
- package/dist/src/capnp/nodeTxList.capnp.js +34 -0
- package/dist/src/capnp/nodeTxList.capnp.js.map +1 -0
- package/dist/src/capnp/paramAcctRec.capnp.d.ts +338 -0
- package/dist/src/capnp/paramAcctRec.capnp.js +669 -0
- package/dist/src/capnp/paramAcctRec.capnp.js.map +1 -0
- package/dist/src/capnp/payload.capnp.d.ts +237 -0
- package/dist/src/capnp/payload.capnp.js +260 -0
- package/dist/src/capnp/payload.capnp.js.map +1 -0
- package/dist/src/capnp/proxyAcctRec.capnp.d.ts +223 -0
- package/dist/src/capnp/proxyAcctRec.capnp.js +255 -0
- package/dist/src/capnp/proxyAcctRec.capnp.js.map +1 -0
- package/dist/src/capnp/relayContentStmt.capnp.d.ts +82 -0
- package/dist/src/capnp/relayContentStmt.capnp.js +85 -0
- package/dist/src/capnp/relayContentStmt.capnp.js.map +1 -0
- package/dist/src/capnp/sysAcctRec.capnp.d.ts +48 -0
- package/dist/src/capnp/sysAcctRec.capnp.js +46 -0
- package/dist/src/capnp/sysAcctRec.capnp.js.map +1 -0
- package/dist/src/capnp/userAppTx.capnp.d.ts +230 -0
- package/dist/src/capnp/userAppTx.capnp.js +270 -0
- package/dist/src/capnp/userAppTx.capnp.js.map +1 -0
- package/dist/src/capnp/userValTx.capnp.d.ts +1575 -0
- package/dist/src/capnp/userValTx.capnp.js +2004 -0
- package/dist/src/capnp/userValTx.capnp.js.map +1 -0
- package/dist/src/capnp/valLayBlock.capnp.d.ts +88 -0
- package/dist/src/capnp/valLayBlock.capnp.js +86 -0
- package/dist/src/capnp/valLayBlock.capnp.js.map +1 -0
- package/dist/src/capnp/valLayLedger.capnp.d.ts +85 -0
- package/dist/src/capnp/valLayLedger.capnp.js +75 -0
- package/dist/src/capnp/valLayLedger.capnp.js.map +1 -0
- package/dist/src/chain/geeq-chain.d.ts +474 -0
- package/dist/src/chain/geeq-chain.js +721 -0
- package/dist/src/chain/geeq-chain.js.map +1 -0
- package/dist/src/chain/geeq-node.d.ts +57 -0
- package/dist/src/chain/geeq-node.js +62 -0
- package/dist/src/chain/geeq-node.js.map +1 -0
- package/dist/src/chain/nonce-guard.d.ts +42 -0
- package/dist/src/chain/nonce-guard.js +68 -0
- package/dist/src/chain/nonce-guard.js.map +1 -0
- package/dist/src/chain/select.d.ts +40 -0
- package/dist/src/chain/select.js +114 -0
- package/dist/src/chain/select.js.map +1 -0
- package/dist/src/crypto/account-id.d.ts +35 -0
- package/dist/src/crypto/account-id.js +58 -0
- package/dist/src/crypto/account-id.js.map +1 -0
- package/dist/src/crypto/keypair.d.ts +24 -0
- package/dist/src/crypto/keypair.js +158 -0
- package/dist/src/crypto/keypair.js.map +1 -0
- package/dist/src/crypto/mnemonic.d.ts +34 -0
- package/dist/src/crypto/mnemonic.js +57 -0
- package/dist/src/crypto/mnemonic.js.map +1 -0
- package/dist/src/encoding/base64.d.ts +8 -0
- package/dist/src/encoding/base64.js +53 -0
- package/dist/src/encoding/base64.js.map +1 -0
- package/dist/src/encoding/hex.d.ts +2 -0
- package/dist/src/encoding/hex.js +35 -0
- package/dist/src/encoding/hex.js.map +1 -0
- package/dist/src/errors.d.ts +83 -0
- package/dist/src/errors.js +49 -0
- package/dist/src/errors.js.map +1 -0
- package/dist/src/index.d.ts +59 -0
- package/dist/src/index.js +53 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/ledger/coin-accounts.d.ts +42 -0
- package/dist/src/ledger/coin-accounts.js +37 -0
- package/dist/src/ledger/coin-accounts.js.map +1 -0
- package/dist/src/ledger/decode.d.ts +18 -0
- package/dist/src/ledger/decode.js +113 -0
- package/dist/src/ledger/decode.js.map +1 -0
- package/dist/src/ledger/geeq-ledger.d.ts +99 -0
- package/dist/src/ledger/geeq-ledger.js +125 -0
- package/dist/src/ledger/geeq-ledger.js.map +1 -0
- package/dist/src/ledger/net-actors.d.ts +65 -0
- package/dist/src/ledger/net-actors.js +53 -0
- package/dist/src/ledger/net-actors.js.map +1 -0
- package/dist/src/ledger/nft-records.d.ts +13 -0
- package/dist/src/ledger/nft-records.js +41 -0
- package/dist/src/ledger/nft-records.js.map +1 -0
- package/dist/src/ledger/params.d.ts +34 -0
- package/dist/src/ledger/params.js +71 -0
- package/dist/src/ledger/params.js.map +1 -0
- package/dist/src/ledger/proxy-accounts.d.ts +26 -0
- package/dist/src/ledger/proxy-accounts.js +27 -0
- package/dist/src/ledger/proxy-accounts.js.map +1 -0
- package/dist/src/net/discovery.d.ts +62 -0
- package/dist/src/net/discovery.js +136 -0
- package/dist/src/net/discovery.js.map +1 -0
- package/dist/src/net/explorer.d.ts +57 -0
- package/dist/src/net/explorer.js +64 -0
- package/dist/src/net/explorer.js.map +1 -0
- package/dist/src/net/read-ledger.d.ts +7 -0
- package/dist/src/net/read-ledger.js +39 -0
- package/dist/src/net/read-ledger.js.map +1 -0
- package/dist/src/net/routes.d.ts +49 -0
- package/dist/src/net/routes.js +70 -0
- package/dist/src/net/routes.js.map +1 -0
- package/dist/src/net/transport.d.ts +55 -0
- package/dist/src/net/transport.js +168 -0
- package/dist/src/net/transport.js.map +1 -0
- package/dist/src/net/websocket.d.ts +49 -0
- package/dist/src/net/websocket.js +54 -0
- package/dist/src/net/websocket.js.map +1 -0
- package/dist/src/runtime/bindings.d.ts +9 -0
- package/dist/src/runtime/bindings.js +27 -0
- package/dist/src/runtime/bindings.js.map +1 -0
- package/dist/src/runtime/init.d.ts +13 -0
- package/dist/src/runtime/init.js +40 -0
- package/dist/src/runtime/init.js.map +1 -0
- package/dist/src/runtime/wasm-loader.browser.d.ts +14 -0
- package/dist/src/runtime/wasm-loader.browser.js +20 -0
- package/dist/src/runtime/wasm-loader.browser.js.map +1 -0
- package/dist/src/runtime/wasm-loader.node.d.ts +7 -0
- package/dist/src/runtime/wasm-loader.node.js +14 -0
- package/dist/src/runtime/wasm-loader.node.js.map +1 -0
- package/dist/src/socket/geeq-socket.d.ts +232 -0
- package/dist/src/socket/geeq-socket.js +634 -0
- package/dist/src/socket/geeq-socket.js.map +1 -0
- package/dist/src/socket/tracked-tx.d.ts +148 -0
- package/dist/src/socket/tracked-tx.js +212 -0
- package/dist/src/socket/tracked-tx.js.map +1 -0
- package/dist/src/socket/tx-status.d.ts +69 -0
- package/dist/src/socket/tx-status.js +72 -0
- package/dist/src/socket/tx-status.js.map +1 -0
- package/dist/src/tx/attestation.d.ts +60 -0
- package/dist/src/tx/attestation.js +163 -0
- package/dist/src/tx/attestation.js.map +1 -0
- package/dist/src/tx/content.d.ts +27 -0
- package/dist/src/tx/content.js +62 -0
- package/dist/src/tx/content.js.map +1 -0
- package/dist/src/tx/encode.d.ts +60 -0
- package/dist/src/tx/encode.js +82 -0
- package/dist/src/tx/encode.js.map +1 -0
- package/dist/src/tx/expiry.d.ts +11 -0
- package/dist/src/tx/expiry.js +12 -0
- package/dist/src/tx/expiry.js.map +1 -0
- package/dist/src/tx/fee.d.ts +16 -0
- package/dist/src/tx/fee.js +29 -0
- package/dist/src/tx/fee.js.map +1 -0
- package/dist/src/tx/metadata.d.ts +39 -0
- package/dist/src/tx/metadata.js +66 -0
- package/dist/src/tx/metadata.js.map +1 -0
- package/dist/src/tx/nft.d.ts +16 -0
- package/dist/src/tx/nft.js +98 -0
- package/dist/src/tx/nft.js.map +1 -0
- package/dist/src/tx/proxy.d.ts +37 -0
- package/dist/src/tx/proxy.js +134 -0
- package/dist/src/tx/proxy.js.map +1 -0
- package/dist/src/tx/transfer.d.ts +31 -0
- package/dist/src/tx/transfer.js +123 -0
- package/dist/src/tx/transfer.js.map +1 -0
- package/dist/src/types.d.ts +448 -0
- package/dist/src/types.js +2 -0
- package/dist/src/types.js.map +1 -0
- package/dist/tests/account-id.test.d.ts +1 -0
- package/dist/tests/account-id.test.js +27 -0
- package/dist/tests/account-id.test.js.map +1 -0
- package/dist/tests/amount.test.d.ts +1 -0
- package/dist/tests/amount.test.js +113 -0
- package/dist/tests/amount.test.js.map +1 -0
- package/dist/tests/attestation.test.d.ts +1 -0
- package/dist/tests/attestation.test.js +182 -0
- package/dist/tests/attestation.test.js.map +1 -0
- package/dist/tests/chain.test.d.ts +1 -0
- package/dist/tests/chain.test.js +647 -0
- package/dist/tests/chain.test.js.map +1 -0
- package/dist/tests/content.test.d.ts +1 -0
- package/dist/tests/content.test.js +90 -0
- package/dist/tests/content.test.js.map +1 -0
- package/dist/tests/documented-api.test.d.ts +1 -0
- package/dist/tests/documented-api.test.js +229 -0
- package/dist/tests/documented-api.test.js.map +1 -0
- package/dist/tests/explorer.test.d.ts +1 -0
- package/dist/tests/explorer.test.js +95 -0
- package/dist/tests/explorer.test.js.map +1 -0
- package/dist/tests/fee.test.d.ts +1 -0
- package/dist/tests/fee.test.js +179 -0
- package/dist/tests/fee.test.js.map +1 -0
- package/dist/tests/fixtures/build-vll.d.ts +71 -0
- package/dist/tests/fixtures/build-vll.js +141 -0
- package/dist/tests/fixtures/build-vll.js.map +1 -0
- package/dist/tests/fixtures/fake-socket.d.ts +44 -0
- package/dist/tests/fixtures/fake-socket.js +93 -0
- package/dist/tests/fixtures/fake-socket.js.map +1 -0
- package/dist/tests/fixtures/fake-transport.d.ts +24 -0
- package/dist/tests/fixtures/fake-transport.js +30 -0
- package/dist/tests/fixtures/fake-transport.js.map +1 -0
- package/dist/tests/keypair.test.d.ts +1 -0
- package/dist/tests/keypair.test.js +163 -0
- package/dist/tests/keypair.test.js.map +1 -0
- package/dist/tests/ledger.test.d.ts +1 -0
- package/dist/tests/ledger.test.js +234 -0
- package/dist/tests/ledger.test.js.map +1 -0
- package/dist/tests/mnemonic.test.d.ts +1 -0
- package/dist/tests/mnemonic.test.js +97 -0
- package/dist/tests/mnemonic.test.js.map +1 -0
- package/dist/tests/nft-transfer.test.d.ts +1 -0
- package/dist/tests/nft-transfer.test.js +170 -0
- package/dist/tests/nft-transfer.test.js.map +1 -0
- package/dist/tests/nft.test.d.ts +1 -0
- package/dist/tests/nft.test.js +180 -0
- package/dist/tests/nft.test.js.map +1 -0
- package/dist/tests/offline.test.d.ts +1 -0
- package/dist/tests/offline.test.js +95 -0
- package/dist/tests/offline.test.js.map +1 -0
- package/dist/tests/proxy.test.d.ts +1 -0
- package/dist/tests/proxy.test.js +183 -0
- package/dist/tests/proxy.test.js.map +1 -0
- package/dist/tests/select.test.d.ts +1 -0
- package/dist/tests/select.test.js +200 -0
- package/dist/tests/select.test.js.map +1 -0
- package/dist/tests/socket.test.d.ts +1 -0
- package/dist/tests/socket.test.js +607 -0
- package/dist/tests/socket.test.js.map +1 -0
- package/dist/tests/transfer.test.d.ts +1 -0
- package/dist/tests/transfer.test.js +225 -0
- package/dist/tests/transfer.test.js.map +1 -0
- package/dist/tests/wallet-address.test.d.ts +1 -0
- package/dist/tests/wallet-address.test.js +101 -0
- package/dist/tests/wallet-address.test.js.map +1 -0
- package/dist/tests/wasm-loader.jest.d.ts +13 -0
- package/dist/tests/wasm-loader.jest.js +15 -0
- package/dist/tests/wasm-loader.jest.js.map +1 -0
- package/example/.env.example +4 -0
- package/example/README.md +304 -0
- package/example/USAGE.md +74 -0
- package/example/index.html +12 -0
- package/example/package-lock.json +1557 -0
- package/example/package.json +25 -0
- package/example/scripts/browser-check.mjs +1421 -0
- package/example/scripts/match-derivation.mjs +65 -0
- package/example/src/App.vue +138 -0
- package/example/src/components/AuthorityPanel.vue +277 -0
- package/example/src/components/ChainPanel.vue +267 -0
- package/example/src/components/ChainState.vue +59 -0
- package/example/src/components/CopyButton.vue +25 -0
- package/example/src/components/CreateAssetPanel.vue +313 -0
- package/example/src/components/DigitalAssetsPanel.vue +68 -0
- package/example/src/components/EvidencePanel.vue +396 -0
- package/example/src/components/ExplorerPanel.vue +119 -0
- package/example/src/components/KeypairPanel.vue +182 -0
- package/example/src/components/PhrasePanel.vue +105 -0
- package/example/src/components/SocketWarning.vue +18 -0
- package/example/src/components/StepGate.vue +24 -0
- package/example/src/components/TransferPanel.vue +416 -0
- package/example/src/components/TxDeadline.vue +19 -0
- package/example/src/components/TxFee.vue +31 -0
- package/example/src/components/TxStatus.vue +105 -0
- package/example/src/composables/useSocketConnection.ts +80 -0
- package/example/src/env.d.ts +12 -0
- package/example/src/main.ts +5 -0
- package/example/src/pennies.ts +7 -0
- package/example/src/style.css +149 -0
- package/example/tsconfig.json +19 -0
- package/example/vite.config.ts +26 -0
- package/jest.config.js +18 -0
- package/package.json +2 -6
- package/scripts/copy-wasm.mjs +21 -0
- package/scripts/smoke.mjs +382 -0
- package/src/address/record-type.ts +77 -0
- package/src/address/wallet-address.ts +105 -0
- package/src/amount.ts +143 -0
- package/src/assert.ts +30 -0
- package/src/capnp/README.md +15 -0
- package/src/capnp/adminNetTx.capnp.ts +66 -0
- package/src/capnp/appLayBlock.capnp.ts +26 -0
- package/src/capnp/appLayLedger.capnp.ts +35 -0
- package/src/capnp/appLayRec.capnp.ts +159 -0
- package/src/capnp/chainStateView.capnp.ts +49 -0
- package/src/capnp/coinAcctRec.capnp.ts +193 -0
- package/src/capnp/genesisBlock.capnp.ts +56 -0
- package/src/capnp/hubContentStmt.capnp.ts +59 -0
- package/src/capnp/misc.capnp.ts +19 -0
- package/src/capnp/netActorRec.capnp.ts +64 -0
- package/src/capnp/nodeContentStmt.capnp.ts +62 -0
- package/src/capnp/nodePayloadList.capnp.ts +28 -0
- package/src/capnp/nodeTxList.capnp.ts +37 -0
- package/src/capnp/paramAcctRec.capnp.ts +669 -0
- package/src/capnp/payload.capnp.ts +261 -0
- package/src/capnp/proxyAcctRec.capnp.ts +259 -0
- package/src/capnp/relayContentStmt.capnp.ts +85 -0
- package/src/capnp/sysAcctRec.capnp.ts +47 -0
- package/src/capnp/userAppTx.capnp.ts +269 -0
- package/src/capnp/userValTx.capnp.ts +1999 -0
- package/src/capnp/valLayBlock.capnp.ts +93 -0
- package/src/capnp/valLayLedger.capnp.ts +80 -0
- package/src/chain/geeq-chain.ts +1094 -0
- package/src/chain/geeq-node.ts +105 -0
- package/src/chain/nonce-guard.ts +73 -0
- package/src/chain/select.ts +149 -0
- package/src/crypto/account-id.ts +83 -0
- package/src/crypto/keypair.ts +221 -0
- package/src/crypto/mnemonic.ts +69 -0
- package/src/encoding/base64.ts +58 -0
- package/src/encoding/hex.ts +42 -0
- package/src/errors.ts +122 -0
- package/src/index.ts +195 -0
- package/src/ledger/coin-accounts.ts +73 -0
- package/src/ledger/decode.ts +147 -0
- package/src/ledger/geeq-ledger.ts +184 -0
- package/src/ledger/net-actors.ts +129 -0
- package/src/ledger/nft-records.ts +49 -0
- package/src/ledger/params.ts +82 -0
- package/src/ledger/proxy-accounts.ts +51 -0
- package/src/net/discovery.ts +231 -0
- package/src/net/explorer.ts +123 -0
- package/src/net/read-ledger.ts +58 -0
- package/src/net/routes.ts +79 -0
- package/src/net/transport.ts +221 -0
- package/src/net/websocket.ts +94 -0
- package/src/runtime/bindings.ts +38 -0
- package/src/runtime/init.ts +49 -0
- package/src/runtime/wasm-loader.browser.ts +22 -0
- package/src/runtime/wasm-loader.node.ts +16 -0
- package/src/socket/geeq-socket.ts +827 -0
- package/src/socket/tracked-tx.ts +319 -0
- package/src/socket/tx-status.ts +131 -0
- package/src/tx/attestation.ts +222 -0
- package/src/tx/content.ts +82 -0
- package/src/tx/encode.ts +107 -0
- package/src/tx/expiry.ts +11 -0
- package/src/tx/fee.ts +31 -0
- package/src/tx/metadata.ts +100 -0
- package/src/tx/nft.ts +108 -0
- package/src/tx/proxy.ts +156 -0
- package/src/tx/transfer.ts +162 -0
- package/src/types.ts +503 -0
- package/src/wasm/README.md +22 -0
- package/src/wasm/browser/geeq_core.d.ts +1224 -0
- package/src/wasm/browser/geeq_core.js +6014 -0
- package/src/wasm/browser/geeq_core_bg.wasm +0 -0
- package/src/wasm/browser/geeq_core_bg.wasm.d.ts +447 -0
- package/src/wasm/nodejs/geeq_core.d.ts +753 -0
- package/src/wasm/nodejs/geeq_core.js +6016 -0
- package/src/wasm/nodejs/geeq_core_bg.wasm +0 -0
- package/src/wasm/nodejs/geeq_core_bg.wasm.d.ts +447 -0
- package/src/wasm/nodejs/package.json +3 -0
- package/tsconfig.build.json +8 -0
- package/tsconfig.json +21 -0
- package/tsup.config.ts +60 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { blake3 } from '@noble/hashes/blake3';
|
|
2
|
+
import { Message } from 'capnp-ts';
|
|
3
|
+
import { AttestationSubgroup as CapnpAttestationSubgroup, Payload as CapnpPayload, } from '../capnp/payload.capnp';
|
|
4
|
+
import { UserAppTx as CapnpUserAppTx } from '../capnp/userAppTx.capnp';
|
|
5
|
+
import { toBase64 } from '../encoding/base64';
|
|
6
|
+
import { assertMetadataWithinLimits, encodeMetadata } from './metadata';
|
|
7
|
+
import { ATTEST_HASH_BYTES, assertAttestHash } from './content';
|
|
8
|
+
import { REF_HASH_BYTES, assertChainState, assertKeypair, flatten, packed, pinning, resolveChainState, } from './encode';
|
|
9
|
+
import { feeFor } from './fee';
|
|
10
|
+
import { WasmAttestationSubgroupData, WasmPayload, WasmUserAppTx, WasmUserAppTxData, } from '../runtime/bindings';
|
|
11
|
+
import { assertReady, initGeeq } from '../runtime/init';
|
|
12
|
+
import { ACCOUNT_ID_BYTES, PUBLIC_KEY_BYTES } from '../crypto/account-id';
|
|
13
|
+
/**
|
|
14
|
+
* Build and sign an attestation subgroup: a hash, its labels, and the account vouching
|
|
15
|
+
* for them. An attestation and an NFT mint carry the same subgroup; it names the signer's
|
|
16
|
+
* own account in one and the minting proxy in the other.
|
|
17
|
+
*
|
|
18
|
+
* Also returns the signature-excluded flatten — what was signed, and what an NFT's id is
|
|
19
|
+
* the hash of.
|
|
20
|
+
*
|
|
21
|
+
* @internal
|
|
22
|
+
*/
|
|
23
|
+
export function signAttestationSubgroup(input) {
|
|
24
|
+
const { keypair, attestHash, metadata } = input;
|
|
25
|
+
const message = new Message();
|
|
26
|
+
const subgroup = message.initRoot(CapnpAttestationSubgroup);
|
|
27
|
+
const data = subgroup.initData();
|
|
28
|
+
data.setChainNum(input.chainNumber);
|
|
29
|
+
data.initAttestHash(ATTEST_HASH_BYTES);
|
|
30
|
+
data.getAttestHash().copyBuffer(attestHash);
|
|
31
|
+
data.initAcctNumVal(ACCOUNT_ID_BYTES);
|
|
32
|
+
data.getAcctNumVal().copyBuffer(input.accountId);
|
|
33
|
+
data.initPubKey(PUBLIC_KEY_BYTES);
|
|
34
|
+
data.getPubKey().copyBuffer(keypair.publicKey);
|
|
35
|
+
data.initMetadata(metadata.length);
|
|
36
|
+
const metadataList = data.getMetadata();
|
|
37
|
+
metadata.forEach((item, index) => {
|
|
38
|
+
const entry = metadataList.get(index);
|
|
39
|
+
// Subgroup positions are 1-based throughout the protocol, so the first label is
|
|
40
|
+
// position 1. The node sorts by this field on read, which is what preserves the
|
|
41
|
+
// order the caller gave.
|
|
42
|
+
entry.setPosition(index + 1);
|
|
43
|
+
entry.initItem(item.length);
|
|
44
|
+
entry.getItem().copyBuffer(item);
|
|
45
|
+
});
|
|
46
|
+
// The subgroup is signed over its data alone, before the signature field exists.
|
|
47
|
+
const flattened = flatten(() => WasmAttestationSubgroupData.fromAttestationSubgroupCapnp(packed(message)), 'attestation subgroup');
|
|
48
|
+
const signature = keypair.sign(flattened);
|
|
49
|
+
subgroup.initSignature(signature.length);
|
|
50
|
+
subgroup.getSignature().copyBuffer(signature);
|
|
51
|
+
return { subgroup, flattened };
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* A payload as it is submitted, the hash its transaction references it by, and its
|
|
55
|
+
* flattened size, which the fee charges for.
|
|
56
|
+
*
|
|
57
|
+
* @internal
|
|
58
|
+
*/
|
|
59
|
+
export function packPayload(message) {
|
|
60
|
+
const flattened = flatten(() => WasmPayload.fromPayloadCapnp(packed(message)), 'payload');
|
|
61
|
+
return {
|
|
62
|
+
payload: toBase64(packed(message)),
|
|
63
|
+
refHashPayload: blake3(flattened, { dkLen: REF_HASH_BYTES }),
|
|
64
|
+
bytes: flattened.length,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Sign a built application-layer transaction and work out the id the node files it under.
|
|
69
|
+
* Every application-layer transaction — an attestation, an NFT mint — ends this way.
|
|
70
|
+
*
|
|
71
|
+
* @internal
|
|
72
|
+
*/
|
|
73
|
+
export function signAppTx(message, tx, keypair) {
|
|
74
|
+
// Signed over the signature-EXCLUDED flatten. The node verifies against exactly this
|
|
75
|
+
// form: its flatten worker swaps in the `…Data` class whenever the signature is left
|
|
76
|
+
// out, and its signature check asks for the flatten without one.
|
|
77
|
+
const flattened = flatten(() => WasmUserAppTxData.fromUserAppTxCapnp(packed(message)), 'transaction');
|
|
78
|
+
const signature = keypair.sign(flattened);
|
|
79
|
+
tx.initSignature(signature.length);
|
|
80
|
+
tx.getSignature().copyBuffer(signature);
|
|
81
|
+
// The chain identifies a transaction by the hash of its signature-INCLUDED flatten —
|
|
82
|
+
// that is the value its status events carry. Hashing the signing preimage instead
|
|
83
|
+
// yields a plausible-looking 32 bytes that no node has ever heard of, so this has to
|
|
84
|
+
// happen after the signature is attached, and through the non-Data class. The same
|
|
85
|
+
// flatten is what the fee charges for.
|
|
86
|
+
const signed = flatten(() => WasmUserAppTx.fromUserAppTxCapnp(packed(message)), 'signed transaction');
|
|
87
|
+
return {
|
|
88
|
+
transaction: toBase64(packed(message)),
|
|
89
|
+
transactionHash: blake3(signed, { dkLen: REF_HASH_BYTES }),
|
|
90
|
+
bytes: signed.length,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Build and sign an attestation transaction. Synchronous; requires a loaded engine.
|
|
95
|
+
*
|
|
96
|
+
* This function is offline: it opens no sockets and reads no ledger. It needs chain
|
|
97
|
+
* state that only a node can supply, so either pass the four values yourself or let
|
|
98
|
+
* {@link GeeqChain} read them and hand you a `chainState`.
|
|
99
|
+
*
|
|
100
|
+
* The transaction is signed but **not submitted**. Post
|
|
101
|
+
* {@link AttestationTx.transaction} and {@link AttestationTx.payload} to the node named
|
|
102
|
+
* by {@link AttestationTx.nodeUrl}.
|
|
103
|
+
*/
|
|
104
|
+
export function createAttestationTxSync(input) {
|
|
105
|
+
assertReady('createAttestationTxSync');
|
|
106
|
+
const { keypair, attestHash } = input;
|
|
107
|
+
const chainState = resolveChainState(input);
|
|
108
|
+
const { chainNumber, blockNumber, nodeNumber, nonce } = chainState;
|
|
109
|
+
assertKeypair(keypair);
|
|
110
|
+
assertAttestHash(attestHash);
|
|
111
|
+
assertChainState(chainState);
|
|
112
|
+
const metadata = encodeMetadata(input.metadata);
|
|
113
|
+
assertMetadataWithinLimits(metadata, chainState.metadataLimits, { chainNumber, blockNumber });
|
|
114
|
+
// 1. The attestation subgroup: what is being attested, and by whom. The account's
|
|
115
|
+
// identifying record number is the BLAKE3 of its public key, which is exactly the
|
|
116
|
+
// account id the keypair already carries.
|
|
117
|
+
const { subgroup } = signAttestationSubgroup({
|
|
118
|
+
keypair,
|
|
119
|
+
attestHash,
|
|
120
|
+
metadata,
|
|
121
|
+
chainNumber,
|
|
122
|
+
accountId: keypair.accountId,
|
|
123
|
+
});
|
|
124
|
+
// 2. The payload carries the signed subgroup.
|
|
125
|
+
const payloadMessage = new Message();
|
|
126
|
+
const payloadRoot = payloadMessage.initRoot(CapnpPayload);
|
|
127
|
+
payloadRoot.initTxType().initAttestCommit();
|
|
128
|
+
payloadRoot.getTxType().getAttestCommit().setAttestationSubgroup(subgroup);
|
|
129
|
+
const { payload, refHashPayload, bytes: payloadBytes } = packPayload(payloadMessage);
|
|
130
|
+
// 3. The transaction references the payload by hash rather than carrying it, and
|
|
131
|
+
// names the block and node that should process it.
|
|
132
|
+
const txMessage = new Message();
|
|
133
|
+
const tx = txMessage.initRoot(CapnpUserAppTx);
|
|
134
|
+
const txData = tx.getData();
|
|
135
|
+
txData.initTxType().initAttestCommit();
|
|
136
|
+
txData.getTxType().getAttestCommit().initAcctNumVal().setNone();
|
|
137
|
+
txData.setChainNum(chainNumber);
|
|
138
|
+
txData.setBlockNum(blockNumber);
|
|
139
|
+
txData.setNodeNum(nodeNumber);
|
|
140
|
+
txData.setNonce(nonce);
|
|
141
|
+
txData.initRefHashPayload(refHashPayload.length);
|
|
142
|
+
txData.getRefHashPayload().copyBuffer(refHashPayload);
|
|
143
|
+
txData.initPubKey(PUBLIC_KEY_BYTES);
|
|
144
|
+
txData.getPubKey().copyBuffer(keypair.publicKey);
|
|
145
|
+
const { transaction, transactionHash, bytes } = signAppTx(txMessage, tx, keypair);
|
|
146
|
+
return Object.freeze({
|
|
147
|
+
transaction,
|
|
148
|
+
payload,
|
|
149
|
+
refHashPayload,
|
|
150
|
+
transactionHash,
|
|
151
|
+
publicKey: keypair.publicKey,
|
|
152
|
+
// An attestation sends no coin, so it pays only for its bytes: the transaction's and
|
|
153
|
+
// the payload's.
|
|
154
|
+
fee: feeFor(bytes + payloadBytes, 0n, chainState.geeqNorm),
|
|
155
|
+
...pinning(chainState),
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
/** Build and sign an attestation transaction, loading the engine if needed. */
|
|
159
|
+
export async function createAttestationTx(input) {
|
|
160
|
+
await initGeeq();
|
|
161
|
+
return createAttestationTxSync(input);
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=attestation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attestation.js","sourceRoot":"","sources":["../../../src/tx/attestation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/** The protocol attests a 32-byte BLAKE3 digest and rejects any other length. */
|
|
2
|
+
export declare const ATTEST_HASH_BYTES = 32;
|
|
3
|
+
/**
|
|
4
|
+
* Anything that can be attested.
|
|
5
|
+
*
|
|
6
|
+
* A `File` from an `<input type="file">` is a `Blob`, so it can be passed straight in —
|
|
7
|
+
* there is no need to read it into a buffer first. A string is encoded as UTF-8.
|
|
8
|
+
*/
|
|
9
|
+
export type GeeqContent = Uint8Array | ArrayBuffer | Blob | string;
|
|
10
|
+
/** Read any accepted content into bytes. Async only because a `Blob` requires it. */
|
|
11
|
+
export declare function readContent(content: GeeqContent): Promise<Uint8Array>;
|
|
12
|
+
/**
|
|
13
|
+
* The digest that goes on chain.
|
|
14
|
+
*
|
|
15
|
+
* The content itself never leaves the device; only this does. Pure BLAKE3, so it needs
|
|
16
|
+
* no engine and no network and works before {@link initGeeq} has resolved — which is
|
|
17
|
+
* what lets a UI show the digest as someone types.
|
|
18
|
+
*
|
|
19
|
+
* Use this rather than calling a hash library directly: the length and the algorithm are
|
|
20
|
+
* both fixed by the protocol, and a digest of any other width is rejected when the
|
|
21
|
+
* transaction is built.
|
|
22
|
+
*/
|
|
23
|
+
export declare function attestHashOfSync(content: Uint8Array | ArrayBuffer | string): Uint8Array;
|
|
24
|
+
/** {@link attestHashOfSync}, also accepting a `Blob` or a `File`. */
|
|
25
|
+
export declare function attestHashOf(content: GeeqContent): Promise<Uint8Array>;
|
|
26
|
+
/** Reject a digest the chain would refuse, naming what was wrong. */
|
|
27
|
+
export declare function assertAttestHash(attestHash: unknown): Uint8Array;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { blake3 } from '@noble/hashes/blake3';
|
|
2
|
+
import { invalidArgument } from '../errors';
|
|
3
|
+
/** The protocol attests a 32-byte BLAKE3 digest and rejects any other length. */
|
|
4
|
+
export const ATTEST_HASH_BYTES = 32;
|
|
5
|
+
/** Read any accepted content into bytes. Async only because a `Blob` requires it. */
|
|
6
|
+
export async function readContent(content) {
|
|
7
|
+
if (content instanceof Uint8Array)
|
|
8
|
+
return content;
|
|
9
|
+
if (typeof content === 'string')
|
|
10
|
+
return new TextEncoder().encode(content);
|
|
11
|
+
if (content instanceof ArrayBuffer)
|
|
12
|
+
return new Uint8Array(content);
|
|
13
|
+
if (typeof Blob !== 'undefined' && content instanceof Blob) {
|
|
14
|
+
return new Uint8Array(await content.arrayBuffer());
|
|
15
|
+
}
|
|
16
|
+
throw invalidArgument('content must be a string, a Uint8Array, an ArrayBuffer, or a Blob (which includes ' +
|
|
17
|
+
'a File from a file input).');
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* The digest that goes on chain.
|
|
21
|
+
*
|
|
22
|
+
* The content itself never leaves the device; only this does. Pure BLAKE3, so it needs
|
|
23
|
+
* no engine and no network and works before {@link initGeeq} has resolved — which is
|
|
24
|
+
* what lets a UI show the digest as someone types.
|
|
25
|
+
*
|
|
26
|
+
* Use this rather than calling a hash library directly: the length and the algorithm are
|
|
27
|
+
* both fixed by the protocol, and a digest of any other width is rejected when the
|
|
28
|
+
* transaction is built.
|
|
29
|
+
*/
|
|
30
|
+
export function attestHashOfSync(content) {
|
|
31
|
+
if (typeof Blob !== 'undefined' && content instanceof Blob) {
|
|
32
|
+
throw invalidArgument('attestHashOfSync cannot read a Blob. Use attestHashOf, which awaits it.');
|
|
33
|
+
}
|
|
34
|
+
const bytes = content instanceof Uint8Array
|
|
35
|
+
? content
|
|
36
|
+
: typeof content === 'string'
|
|
37
|
+
? new TextEncoder().encode(content)
|
|
38
|
+
: content instanceof ArrayBuffer
|
|
39
|
+
? new Uint8Array(content)
|
|
40
|
+
: undefined;
|
|
41
|
+
if (bytes === undefined) {
|
|
42
|
+
throw invalidArgument('content must be a string, a Uint8Array or an ArrayBuffer. For a Blob or a File, ' +
|
|
43
|
+
'use attestHashOf.');
|
|
44
|
+
}
|
|
45
|
+
return blake3(bytes, { dkLen: ATTEST_HASH_BYTES });
|
|
46
|
+
}
|
|
47
|
+
/** {@link attestHashOfSync}, also accepting a `Blob` or a `File`. */
|
|
48
|
+
export async function attestHashOf(content) {
|
|
49
|
+
return blake3(await readContent(content), { dkLen: ATTEST_HASH_BYTES });
|
|
50
|
+
}
|
|
51
|
+
/** Reject a digest the chain would refuse, naming what was wrong. */
|
|
52
|
+
export function assertAttestHash(attestHash) {
|
|
53
|
+
if (!(attestHash instanceof Uint8Array)) {
|
|
54
|
+
throw invalidArgument('attestHash must be a Uint8Array.');
|
|
55
|
+
}
|
|
56
|
+
if (attestHash.length !== ATTEST_HASH_BYTES) {
|
|
57
|
+
throw invalidArgument(`attestHash must be ${ATTEST_HASH_BYTES} bytes, received ${attestHash.length}. ` +
|
|
58
|
+
'Use attestHashOf() to produce one.');
|
|
59
|
+
}
|
|
60
|
+
return attestHash;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=content.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content.js","sourceRoot":"","sources":["../../../src/tx/content.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAE7C,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAE3C,iFAAiF;AACjF,MAAM,CAAC,MAAM,iBAAiB,GAAG,EAAE,CAAA;AAUnC,qFAAqF;AACrF,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAoB;IACpD,IAAI,OAAO,YAAY,UAAU;QAAE,OAAO,OAAO,CAAA;IACjD,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;IACzE,IAAI,OAAO,YAAY,WAAW;QAAE,OAAO,IAAI,UAAU,CAAC,OAAO,CAAC,CAAA;IAClE,IAAI,OAAO,IAAI,KAAK,WAAW,IAAI,OAAO,YAAY,IAAI,EAAE,CAAC;QAC3D,OAAO,IAAI,UAAU,CAAC,MAAM,OAAO,CAAC,WAAW,EAAE,CAAC,CAAA;IACpD,CAAC;IACD,MAAM,eAAe,CACnB,oFAAoF;QAClF,4BAA4B,CAC/B,CAAA;AACH,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAA0C;IACzE,IAAI,OAAO,IAAI,KAAK,WAAW,IAAI,OAAO,YAAY,IAAI,EAAE,CAAC;QAC3D,MAAM,eAAe,CACnB,yEAAyE,CAC1E,CAAA;IACH,CAAC;IACD,MAAM,KAAK,GACT,OAAO,YAAY,UAAU;QAC3B,CAAC,CAAC,OAAO;QACT,CAAC,CAAC,OAAO,OAAO,KAAK,QAAQ;YAC3B,CAAC,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC;YACnC,CAAC,CAAC,OAAO,YAAY,WAAW;gBAC9B,CAAC,CAAC,IAAI,UAAU,CAAC,OAAO,CAAC;gBACzB,CAAC,CAAC,SAAS,CAAA;IAEnB,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,MAAM,eAAe,CACnB,kFAAkF;YAChF,mBAAmB,CACtB,CAAA;IACH,CAAC;IACD,OAAO,MAAM,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC,CAAA;AACpD,CAAC;AAED,qEAAqE;AACrE,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAAoB;IACrD,OAAO,MAAM,CAAC,MAAM,WAAW,CAAC,OAAO,CAAC,EAAE,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC,CAAA;AACzE,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,gBAAgB,CAAC,UAAmB;IAClD,IAAI,CAAC,CAAC,UAAU,YAAY,UAAU,CAAC,EAAE,CAAC;QACxC,MAAM,eAAe,CAAC,kCAAkC,CAAC,CAAA;IAC3D,CAAC;IACD,IAAI,UAAU,CAAC,MAAM,KAAK,iBAAiB,EAAE,CAAC;QAC5C,MAAM,eAAe,CACnB,sBAAsB,iBAAiB,oBAAoB,UAAU,CAAC,MAAM,IAAI;YAC9E,oCAAoC,CACvC,CAAA;IACH,CAAC;IACD,OAAO,UAAU,CAAA;AACnB,CAAC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { Message } from 'capnp-ts';
|
|
2
|
+
import type { ChainStateInput, GeeqKeypair } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* What every transaction builder shares: the checks on its inputs, the Cap'n Proto
|
|
5
|
+
* packing, the engine's canonical flatten, and the fields every built transaction reports
|
|
6
|
+
* about what it is pinned to. One copy, so the four builders cannot drift apart.
|
|
7
|
+
*
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
/** Every refHash the chain computes is a 32-byte BLAKE3. */
|
|
11
|
+
export declare const REF_HASH_BYTES = 32;
|
|
12
|
+
/** @internal */
|
|
13
|
+
export declare function assertKeypair(keypair: GeeqKeypair): void;
|
|
14
|
+
/** @internal The four numbers a transaction carries are each a uint32 on the wire. */
|
|
15
|
+
export declare function assertChainState(chainState: ChainStateInput): void;
|
|
16
|
+
/** The two shapes a builder accepts chain state in: four numbers, or one object. */
|
|
17
|
+
type FlatOrStateInput = {
|
|
18
|
+
readonly chainState: ChainStateInput;
|
|
19
|
+
} | {
|
|
20
|
+
readonly chainState?: never;
|
|
21
|
+
readonly chainNumber: number;
|
|
22
|
+
readonly blockNumber: number;
|
|
23
|
+
readonly nodeNumber: number;
|
|
24
|
+
readonly nonce: number;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Normalise the two input shapes into one chain state.
|
|
28
|
+
*
|
|
29
|
+
* The flat four-number form is kept for replay and offline signing; the object form is
|
|
30
|
+
* what a chain read produces. Everything after this sees only the object.
|
|
31
|
+
*
|
|
32
|
+
* @internal
|
|
33
|
+
*/
|
|
34
|
+
export declare function resolveChainState(input: FlatOrStateInput): ChainStateInput;
|
|
35
|
+
/**
|
|
36
|
+
* What a built transaction reports about what it is pinned to: the state itself, frozen,
|
|
37
|
+
* the last block a node takes it at, and the node it must go to when a chain read chose it.
|
|
38
|
+
*
|
|
39
|
+
* @internal
|
|
40
|
+
*/
|
|
41
|
+
export declare function pinning(chainState: ChainStateInput): {
|
|
42
|
+
readonly chainState: ChainStateInput;
|
|
43
|
+
readonly validUntilBlock: number;
|
|
44
|
+
readonly nodeUrl?: string;
|
|
45
|
+
};
|
|
46
|
+
/** @internal A message as it is submitted: Cap'n Proto packed. */
|
|
47
|
+
export declare function packed(message: Message): Uint8Array;
|
|
48
|
+
/**
|
|
49
|
+
* Flattening is what makes a signature verifiable by the chain: the engine turns a
|
|
50
|
+
* Cap'n Proto message into the one canonical byte sequence the protocol signs over.
|
|
51
|
+
* Signing the capnp bytes directly would produce a signature every node rejects,
|
|
52
|
+
* because packing is not canonical.
|
|
53
|
+
*
|
|
54
|
+
* @internal
|
|
55
|
+
*/
|
|
56
|
+
export declare function flatten<T extends {
|
|
57
|
+
flatten(): Uint8Array;
|
|
58
|
+
free(): void;
|
|
59
|
+
}>(parse: () => T, what: string): Uint8Array;
|
|
60
|
+
export {};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { assertUint32 } from '../assert';
|
|
2
|
+
import { invalidArgument } from '../errors';
|
|
3
|
+
import { TARGET_BLOCK_SLACK } from './expiry';
|
|
4
|
+
/**
|
|
5
|
+
* What every transaction builder shares: the checks on its inputs, the Cap'n Proto
|
|
6
|
+
* packing, the engine's canonical flatten, and the fields every built transaction reports
|
|
7
|
+
* about what it is pinned to. One copy, so the four builders cannot drift apart.
|
|
8
|
+
*
|
|
9
|
+
* @internal
|
|
10
|
+
*/
|
|
11
|
+
/** Every refHash the chain computes is a 32-byte BLAKE3. */
|
|
12
|
+
export const REF_HASH_BYTES = 32;
|
|
13
|
+
/** @internal */
|
|
14
|
+
export function assertKeypair(keypair) {
|
|
15
|
+
if (keypair === null || typeof keypair !== 'object' || typeof keypair.sign !== 'function') {
|
|
16
|
+
throw invalidArgument('keypair must be a GeeqKeypair.');
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/** @internal The four numbers a transaction carries are each a uint32 on the wire. */
|
|
20
|
+
export function assertChainState(chainState) {
|
|
21
|
+
assertUint32(chainState.chainNumber, 'chainNumber');
|
|
22
|
+
assertUint32(chainState.blockNumber, 'blockNumber');
|
|
23
|
+
assertUint32(chainState.nodeNumber, 'nodeNumber');
|
|
24
|
+
assertUint32(chainState.nonce, 'nonce');
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Normalise the two input shapes into one chain state.
|
|
28
|
+
*
|
|
29
|
+
* The flat four-number form is kept for replay and offline signing; the object form is
|
|
30
|
+
* what a chain read produces. Everything after this sees only the object.
|
|
31
|
+
*
|
|
32
|
+
* @internal
|
|
33
|
+
*/
|
|
34
|
+
export function resolveChainState(input) {
|
|
35
|
+
if (input.chainState !== undefined)
|
|
36
|
+
return input.chainState;
|
|
37
|
+
return {
|
|
38
|
+
chainNumber: input.chainNumber,
|
|
39
|
+
blockNumber: input.blockNumber,
|
|
40
|
+
nodeNumber: input.nodeNumber,
|
|
41
|
+
nonce: input.nonce,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* What a built transaction reports about what it is pinned to: the state itself, frozen,
|
|
46
|
+
* the last block a node takes it at, and the node it must go to when a chain read chose it.
|
|
47
|
+
*
|
|
48
|
+
* @internal
|
|
49
|
+
*/
|
|
50
|
+
export function pinning(chainState) {
|
|
51
|
+
return {
|
|
52
|
+
chainState: Object.freeze({ ...chainState }),
|
|
53
|
+
validUntilBlock: chainState.blockNumber + TARGET_BLOCK_SLACK,
|
|
54
|
+
...(chainState.nodeUrl === undefined ? {} : { nodeUrl: chainState.nodeUrl }),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/** @internal A message as it is submitted: Cap'n Proto packed. */
|
|
58
|
+
export function packed(message) {
|
|
59
|
+
return new Uint8Array(message.toPackedArrayBuffer());
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Flattening is what makes a signature verifiable by the chain: the engine turns a
|
|
63
|
+
* Cap'n Proto message into the one canonical byte sequence the protocol signs over.
|
|
64
|
+
* Signing the capnp bytes directly would produce a signature every node rejects,
|
|
65
|
+
* because packing is not canonical.
|
|
66
|
+
*
|
|
67
|
+
* @internal
|
|
68
|
+
*/
|
|
69
|
+
export function flatten(parse, what) {
|
|
70
|
+
let handle;
|
|
71
|
+
try {
|
|
72
|
+
handle = parse();
|
|
73
|
+
return handle.flatten();
|
|
74
|
+
}
|
|
75
|
+
catch (cause) {
|
|
76
|
+
throw invalidArgument(`Could not encode the ${what} for signing.`, cause);
|
|
77
|
+
}
|
|
78
|
+
finally {
|
|
79
|
+
handle?.free();
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=encode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encode.js","sourceRoot":"","sources":["../../../src/tx/encode.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAE3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAA;AAE7C;;;;;;GAMG;AAEH,4DAA4D;AAC5D,MAAM,CAAC,MAAM,cAAc,GAAG,EAAE,CAAA;AAEhC,gBAAgB;AAChB,MAAM,UAAU,aAAa,CAAC,OAAoB;IAChD,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,OAAO,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QAC1F,MAAM,eAAe,CAAC,gCAAgC,CAAC,CAAA;IACzD,CAAC;AACH,CAAC;AAED,sFAAsF;AACtF,MAAM,UAAU,gBAAgB,CAAC,UAA2B;IAC1D,YAAY,CAAC,UAAU,CAAC,WAAW,EAAE,aAAa,CAAC,CAAA;IACnD,YAAY,CAAC,UAAU,CAAC,WAAW,EAAE,aAAa,CAAC,CAAA;IACnD,YAAY,CAAC,UAAU,CAAC,UAAU,EAAE,YAAY,CAAC,CAAA;IACjD,YAAY,CAAC,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;AACzC,CAAC;AAaD;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAuB;IACvD,IAAI,KAAK,CAAC,UAAU,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC,UAAU,CAAA;IAC3D,OAAO;QACL,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,KAAK,EAAE,KAAK,CAAC,KAAK;KACnB,CAAA;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,OAAO,CAAC,UAA2B;IAKjD,OAAO;QACL,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,UAAU,EAAE,CAAC;QAC5C,eAAe,EAAE,UAAU,CAAC,WAAW,GAAG,kBAAkB;QAC5D,GAAG,CAAC,UAAU,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,UAAU,CAAC,OAAO,EAAE,CAAC;KAC7E,CAAA;AACH,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,MAAM,CAAC,OAAgB;IACrC,OAAO,IAAI,UAAU,CAAC,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAA;AACtD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,OAAO,CACrB,KAAc,EACd,IAAY;IAEZ,IAAI,MAAqB,CAAA;IACzB,IAAI,CAAC;QACH,MAAM,GAAG,KAAK,EAAE,CAAA;QAChB,OAAO,MAAM,CAAC,OAAO,EAAE,CAAA;IACzB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,eAAe,CAAC,wBAAwB,IAAI,eAAe,EAAE,KAAK,CAAC,CAAA;IAC3E,CAAC;YAAS,CAAC;QACT,MAAM,EAAE,IAAI,EAAE,CAAA;IAChB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How many blocks the chain may move past a transaction's target block before nodes
|
|
3
|
+
* refuse it.
|
|
4
|
+
*
|
|
5
|
+
* A node accepts a target within `[N-8, N+1]` of its own last committed block N
|
|
6
|
+
* (geeq_node_core `indicator-function-worker.ts`, Block Target Consistency), and answers
|
|
7
|
+
* anything older with an HTTP 400 and a `nonsane` status.
|
|
8
|
+
*
|
|
9
|
+
* @internal
|
|
10
|
+
*/
|
|
11
|
+
export declare const TARGET_BLOCK_SLACK = 8;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How many blocks the chain may move past a transaction's target block before nodes
|
|
3
|
+
* refuse it.
|
|
4
|
+
*
|
|
5
|
+
* A node accepts a target within `[N-8, N+1]` of its own last committed block N
|
|
6
|
+
* (geeq_node_core `indicator-function-worker.ts`, Block Target Consistency), and answers
|
|
7
|
+
* anything older with an HTTP 400 and a `nonsane` status.
|
|
8
|
+
*
|
|
9
|
+
* @internal
|
|
10
|
+
*/
|
|
11
|
+
export const TARGET_BLOCK_SLACK = 8;
|
|
12
|
+
//# sourceMappingURL=expiry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expiry.js","sourceRoot":"","sources":["../../../src/tx/expiry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAA"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { GeeqFee } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* What the chain will charge for a transaction, worked out exactly as the node works it out
|
|
4
|
+
* (geeq_node_core `wrappers/base.ts`, `calculateTransactionFee`):
|
|
5
|
+
*
|
|
6
|
+
* - **data** — `geeqNorm` pennies for every byte of the signed, flattened transaction, and
|
|
7
|
+
* of its flattened payload when it has one;
|
|
8
|
+
* - **coin** — a quarter of a percent of the amount sent, rounded down, and never more than
|
|
9
|
+
* `geeqNorm × 10⁷` pennies. An attestation sends no amount, so it pays only for its data.
|
|
10
|
+
*
|
|
11
|
+
* `undefined` when the chain's `geeqNorm` is not known — the four numbers were supplied by
|
|
12
|
+
* hand, or the chain does not publish it.
|
|
13
|
+
*
|
|
14
|
+
* @internal
|
|
15
|
+
*/
|
|
16
|
+
export declare function feeFor(bytes: number, amount: bigint, geeqNorm: bigint | undefined): GeeqFee | undefined;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { invalidArgument } from '../errors';
|
|
2
|
+
/** The coin part of a fee never exceeds this many times `geeqNorm`, in pennies. */
|
|
3
|
+
const COIN_FEE_CAP = 10000000n;
|
|
4
|
+
/**
|
|
5
|
+
* What the chain will charge for a transaction, worked out exactly as the node works it out
|
|
6
|
+
* (geeq_node_core `wrappers/base.ts`, `calculateTransactionFee`):
|
|
7
|
+
*
|
|
8
|
+
* - **data** — `geeqNorm` pennies for every byte of the signed, flattened transaction, and
|
|
9
|
+
* of its flattened payload when it has one;
|
|
10
|
+
* - **coin** — a quarter of a percent of the amount sent, rounded down, and never more than
|
|
11
|
+
* `geeqNorm × 10⁷` pennies. An attestation sends no amount, so it pays only for its data.
|
|
12
|
+
*
|
|
13
|
+
* `undefined` when the chain's `geeqNorm` is not known — the four numbers were supplied by
|
|
14
|
+
* hand, or the chain does not publish it.
|
|
15
|
+
*
|
|
16
|
+
* @internal
|
|
17
|
+
*/
|
|
18
|
+
export function feeFor(bytes, amount, geeqNorm) {
|
|
19
|
+
if (geeqNorm === undefined)
|
|
20
|
+
return undefined;
|
|
21
|
+
if (typeof geeqNorm !== 'bigint' || geeqNorm < 0n) {
|
|
22
|
+
throw invalidArgument('geeqNorm must be a bigint of zero or more, as the ledger holds it.');
|
|
23
|
+
}
|
|
24
|
+
const data = BigInt(bytes) * geeqNorm;
|
|
25
|
+
const cap = geeqNorm * COIN_FEE_CAP;
|
|
26
|
+
const coin = amount / 400n < cap ? amount / 400n : cap;
|
|
27
|
+
return Object.freeze({ total: data + coin, data, coin, bytes });
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=fee.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fee.js","sourceRoot":"","sources":["../../../src/tx/fee.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAG3C,mFAAmF;AACnF,MAAM,YAAY,GAAG,SAAW,CAAA;AAEhC;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,MAAM,CAAC,KAAa,EAAE,MAAc,EAAE,QAA4B;IAChF,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,SAAS,CAAA;IAC5C,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,GAAG,EAAE,EAAE,CAAC;QAClD,MAAM,eAAe,CAAC,oEAAoE,CAAC,CAAA;IAC7F,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,QAAQ,CAAA;IACrC,MAAM,GAAG,GAAG,QAAQ,GAAG,YAAY,CAAA;IACnC,MAAM,IAAI,GAAG,MAAM,GAAG,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,CAAA;IACtD,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,IAAI,GAAG,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;AACjE,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { GeeqMetadataLimits } from '../types';
|
|
2
|
+
/** Labels are kept in the order given and encoded as UTF-8. */
|
|
3
|
+
export declare function encodeMetadata(metadata: readonly (string | Uint8Array)[] | undefined): Uint8Array[];
|
|
4
|
+
/**
|
|
5
|
+
* Check encoded metadata against the limits the chain publishes in its ledger.
|
|
6
|
+
*
|
|
7
|
+
* The node enforces both of these at submit time, so catching them here turns an
|
|
8
|
+
* opaque HTTP 400 into a message naming the entry and the limit — and does it before
|
|
9
|
+
* anything is signed. Skipped entirely when the ledger carries no such parameters,
|
|
10
|
+
* because a missing parameter is a schema difference, not a caller error.
|
|
11
|
+
*/
|
|
12
|
+
export declare function assertMetadataWithinLimits(encoded: readonly Uint8Array[], limits: GeeqMetadataLimits | undefined, context: {
|
|
13
|
+
readonly chainNumber: number;
|
|
14
|
+
readonly blockNumber: number;
|
|
15
|
+
}): void;
|
|
16
|
+
/** What one metadata entry costs, and whether the chain would take it. */
|
|
17
|
+
export interface MetadataEntryReport {
|
|
18
|
+
readonly index: number;
|
|
19
|
+
/** Length once encoded as UTF-8, which is what the limit is measured in. */
|
|
20
|
+
readonly bytes: number;
|
|
21
|
+
readonly overLimit: boolean;
|
|
22
|
+
}
|
|
23
|
+
export interface MetadataReport {
|
|
24
|
+
readonly entries: readonly MetadataEntryReport[];
|
|
25
|
+
readonly count: number;
|
|
26
|
+
readonly tooManyEntries: boolean;
|
|
27
|
+
readonly withinLimits: boolean;
|
|
28
|
+
/** Undefined when the chain publishes no limits, in which case nothing is checked. */
|
|
29
|
+
readonly limits: GeeqMetadataLimits | undefined;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Measure metadata against a chain's limits without throwing.
|
|
33
|
+
*
|
|
34
|
+
* The same rules {@link assertMetadataWithinLimits} enforces, reported rather than
|
|
35
|
+
* raised, so a UI can colour a field as someone types instead of waiting for a failed
|
|
36
|
+
* build. Byte lengths are UTF-8, which is the only measure that matters here — a label
|
|
37
|
+
* of ten emoji is forty bytes, and counting characters would call it short.
|
|
38
|
+
*/
|
|
39
|
+
export declare function inspectMetadata(metadata: readonly (string | Uint8Array)[] | undefined, limits: GeeqMetadataLimits | undefined): MetadataReport;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { invalidArgument, metadataTooLarge } from '../errors';
|
|
2
|
+
/** Labels are kept in the order given and encoded as UTF-8. */
|
|
3
|
+
export function encodeMetadata(metadata) {
|
|
4
|
+
if (metadata === undefined)
|
|
5
|
+
return [];
|
|
6
|
+
const encoder = new TextEncoder();
|
|
7
|
+
return metadata.map((item, index) => {
|
|
8
|
+
if (typeof item === 'string')
|
|
9
|
+
return encoder.encode(item);
|
|
10
|
+
if (item instanceof Uint8Array)
|
|
11
|
+
return item;
|
|
12
|
+
throw invalidArgument(`metadata[${index}] must be a string or a Uint8Array.`);
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Check encoded metadata against the limits the chain publishes in its ledger.
|
|
17
|
+
*
|
|
18
|
+
* The node enforces both of these at submit time, so catching them here turns an
|
|
19
|
+
* opaque HTTP 400 into a message naming the entry and the limit — and does it before
|
|
20
|
+
* anything is signed. Skipped entirely when the ledger carries no such parameters,
|
|
21
|
+
* because a missing parameter is a schema difference, not a caller error.
|
|
22
|
+
*/
|
|
23
|
+
export function assertMetadataWithinLimits(encoded, limits, context) {
|
|
24
|
+
if (limits === undefined)
|
|
25
|
+
return;
|
|
26
|
+
if (encoded.length > limits.maxEntries) {
|
|
27
|
+
throw metadataTooLarge(`metadata has ${encoded.length} entries but chain ${context.chainNumber} allows at ` +
|
|
28
|
+
`most ${limits.maxEntries} (parameter metadataVarNum, read at block ` +
|
|
29
|
+
`${context.blockNumber}). Remove ${encoded.length - limits.maxEntries}.`);
|
|
30
|
+
}
|
|
31
|
+
for (let index = 0; index < encoded.length; index += 1) {
|
|
32
|
+
const entry = encoded[index];
|
|
33
|
+
if (entry.length > limits.maxBytesPerEntry) {
|
|
34
|
+
throw metadataTooLarge(`metadata[${index}] is ${entry.length} bytes but chain ${context.chainNumber} ` +
|
|
35
|
+
`allows at most ${limits.maxBytesPerEntry} bytes per entry (parameter ` +
|
|
36
|
+
`metadataVarBytes, read at block ${context.blockNumber}). Characters outside ` +
|
|
37
|
+
'ASCII cost more than one byte each once encoded as UTF-8, so shorten it.');
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Measure metadata against a chain's limits without throwing.
|
|
43
|
+
*
|
|
44
|
+
* The same rules {@link assertMetadataWithinLimits} enforces, reported rather than
|
|
45
|
+
* raised, so a UI can colour a field as someone types instead of waiting for a failed
|
|
46
|
+
* build. Byte lengths are UTF-8, which is the only measure that matters here — a label
|
|
47
|
+
* of ten emoji is forty bytes, and counting characters would call it short.
|
|
48
|
+
*/
|
|
49
|
+
export function inspectMetadata(metadata, limits) {
|
|
50
|
+
const encoded = encodeMetadata(metadata);
|
|
51
|
+
const maxBytes = limits?.maxBytesPerEntry;
|
|
52
|
+
const entries = encoded.map((entry, index) => Object.freeze({
|
|
53
|
+
index,
|
|
54
|
+
bytes: entry.length,
|
|
55
|
+
overLimit: maxBytes !== undefined && entry.length > maxBytes,
|
|
56
|
+
}));
|
|
57
|
+
const tooManyEntries = limits !== undefined && encoded.length > limits.maxEntries;
|
|
58
|
+
return Object.freeze({
|
|
59
|
+
entries: Object.freeze(entries),
|
|
60
|
+
count: encoded.length,
|
|
61
|
+
tooManyEntries,
|
|
62
|
+
withinLimits: !tooManyEntries && !entries.some((entry) => entry.overLimit),
|
|
63
|
+
limits,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=metadata.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../../src/tx/metadata.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAA;AAG7D,+DAA+D;AAC/D,MAAM,UAAU,cAAc,CAC5B,QAAsD;IAEtD,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,EAAE,CAAA;IACrC,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAA;IACjC,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QAClC,IAAI,OAAO,IAAI,KAAK,QAAQ;YAAE,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;QACzD,IAAI,IAAI,YAAY,UAAU;YAAE,OAAO,IAAI,CAAA;QAC3C,MAAM,eAAe,CAAC,YAAY,KAAK,qCAAqC,CAAC,CAAA;IAC/E,CAAC,CAAC,CAAA;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,0BAA0B,CACxC,OAA8B,EAC9B,MAAsC,EACtC,OAAuE;IAEvE,IAAI,MAAM,KAAK,SAAS;QAAE,OAAM;IAEhC,IAAI,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;QACvC,MAAM,gBAAgB,CACpB,gBAAgB,OAAO,CAAC,MAAM,sBAAsB,OAAO,CAAC,WAAW,aAAa;YAClF,QAAQ,MAAM,CAAC,UAAU,4CAA4C;YACrE,GAAG,OAAO,CAAC,WAAW,aAAa,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC,UAAU,GAAG,CAC3E,CAAA;IACH,CAAC;IAED,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACvD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAe,CAAA;QAC1C,IAAI,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,gBAAgB,EAAE,CAAC;YAC3C,MAAM,gBAAgB,CACpB,YAAY,KAAK,QAAQ,KAAK,CAAC,MAAM,oBAAoB,OAAO,CAAC,WAAW,GAAG;gBAC7E,kBAAkB,MAAM,CAAC,gBAAgB,8BAA8B;gBACvE,mCAAmC,OAAO,CAAC,WAAW,wBAAwB;gBAC9E,0EAA0E,CAC7E,CAAA;QACH,CAAC;IACH,CAAC;AACH,CAAC;AAmBD;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAC7B,QAAsD,EACtD,MAAsC;IAEtC,MAAM,OAAO,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAA;IACxC,MAAM,QAAQ,GAAG,MAAM,EAAE,gBAAgB,CAAA;IACzC,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAC3C,MAAM,CAAC,MAAM,CAAC;QACZ,KAAK;QACL,KAAK,EAAE,KAAK,CAAC,MAAM;QACnB,SAAS,EAAE,QAAQ,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,GAAG,QAAQ;KAC7D,CAAC,CACH,CAAA;IACD,MAAM,cAAc,GAAG,MAAM,KAAK,SAAS,IAAI,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC,UAAU,CAAA;IAEjF,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;QAC/B,KAAK,EAAE,OAAO,CAAC,MAAM;QACrB,cAAc;QACd,YAAY,EAAE,CAAC,cAAc,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC;QAC1E,MAAM;KACP,CAAC,CAAA;AACJ,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { NftMintTx, NftMintTxInput } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Build and sign an NFT mint. Synchronous; requires a loaded engine.
|
|
4
|
+
*
|
|
5
|
+
* An NFT is minted through a proxy, and the proxy is the sender: it pays the fee and
|
|
6
|
+
* `amount`, which goes to the receiver with the NFT, and it spends its own nonce. Its
|
|
7
|
+
* admin — the signer here — is the only key the chain accepts for it. The NFT itself is an
|
|
8
|
+
* attestation subgroup, as an attestation carries: the content's hash and its labels,
|
|
9
|
+
* signed by the admin and naming the proxy.
|
|
10
|
+
*
|
|
11
|
+
* Offline: it cannot check that the proxy exists, is the signer's, or can pay.
|
|
12
|
+
* {@link GeeqChain.mintNft} does all three.
|
|
13
|
+
*/
|
|
14
|
+
export declare function createNftMintTxSync(input: NftMintTxInput): NftMintTx;
|
|
15
|
+
/** Build and sign an NFT mint, loading the engine if needed. */
|
|
16
|
+
export declare function createNftMintTx(input: NftMintTxInput): Promise<NftMintTx>;
|