diff --git a/CHANGELOG.md b/CHANGELOG.md index ecbdcbea..097b2b53 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,36 +10,6 @@ * **lua:** update lua code id ([76822a2](https://github.com/ar-io/ar-io-sdk/commit/76822a2b4b12df7449d6a0d4c25927d491a17faf)) * **tags:** remove extra tags from spawn util ([f308b84](https://github.com/ar-io/ar-io-sdk/commit/f308b84cb48f7ecb4bd89d5dbc910002bd147dcc)) -## [3.3.1-alpha.4](https://github.com/ar-io/ar-io-sdk/compare/v3.3.1-alpha.3...v3.3.1-alpha.4) (2025-01-29) - - -### Bug Fixes - -* **ant:** update ANT ids ([9f37e76](https://github.com/ar-io/ar-io-sdk/commit/9f37e768b43ad6fb6d813de1eba7eefe072bfb97)) - -## [3.3.1-alpha.3](https://github.com/ar-io/ar-io-sdk/compare/v3.3.1-alpha.2...v3.3.1-alpha.3) (2025-01-28) - - -### Bug Fixes - -* **ant:** bumps ids ([8eb2e38](https://github.com/ar-io/ar-io-sdk/commit/8eb2e388fe15e18b049c735ab414b750b7aa439b)) - -## [3.3.1-alpha.2](https://github.com/ar-io/ar-io-sdk/compare/v3.3.1-alpha.1...v3.3.1-alpha.2) (2025-01-26) - - -### Bug Fixes - -* **boot:** add boot loader logic to ant spawn util ([f00ab47](https://github.com/ar-io/ar-io-sdk/commit/f00ab47848979b05634677ad458940b033e9f90a)) -* **lua:** update lua code id ([76822a2](https://github.com/ar-io/ar-io-sdk/commit/76822a2b4b12df7449d6a0d4c25927d491a17faf)) -* **tags:** remove extra tags from spawn util ([f308b84](https://github.com/ar-io/ar-io-sdk/commit/f308b84cb48f7ecb4bd89d5dbc910002bd147dcc)) - -## [3.3.1-alpha.1](https://github.com/ar-io/ar-io-sdk/compare/v3.3.0...v3.3.1-alpha.1) (2025-01-24) - - -### Bug Fixes - -* **ants:** module bump _wSmbjfSlX3dZNcqE8JqKmj-DKum9uQ_jB08LwOKCyw ([8d442e0](https://github.com/ar-io/ar-io-sdk/commit/8d442e0c6fe102a8890b4b38d4b37c434004842d)) - # [3.3.0](https://github.com/ar-io/ar-io-sdk/compare/v3.2.0...v3.3.0) (2025-01-24) diff --git a/CLI.md b/CLI.md index 9783476e..59b46726 100644 --- a/CLI.md +++ b/CLI.md @@ -123,6 +123,11 @@ Commands: get-gateway-vaults [options] Get the vaults of a gateway list-all-gateway-vaults [options] List vaults from all gateways transfer [options] Transfer ARIO to another address + vaulted-transfer [options] Transfer ARIO to another address into a locked vault + revoke-vault [options] Revoke a vaulted transfer as the controller + create-vault [options] Create a locked vault with balance from the sender + extend-vault [options] Extend the lock length of a vault as the recipient + increase-vault [options] Increase the balance of a locked vault as the recipient join-network [options] Join a gateway to the AR.IO network leave-network [options] Leave a gateway from the AR.IO network update-gateway-settings [options] Update AR.IO gateway settings @@ -153,7 +158,9 @@ Commands: transfer-ant-ownership [options] Transfer ownership of an ANT process add-ant-controller [options] Add a controller to an ANT process remove-ant-controller [options] Remove a controller from an ANT process - set-ant-record [options] Set a record of an ANT process + set-ant-record [options] Set a record of an ANT process. Deprecated: use set-ant-base-name and set-ant-undername + set-ant-base-name [options] Set the base name of an ANT process + set-ant-undername [options] Set an undername of an ANT process remove-ant-record [options] Remove a record from an ANT process set-ant-ticker [options] Set the ticker of an ANT process set-ant-name [options] Set the name of an ANT process diff --git a/README.md b/README.md index 7a621fea..19cac55f 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,11 @@ This is the home of [ar.io] SDK. This SDK provides functionality for interacting - [Vaults](#vaults) - [`getVault({ address, vaultId })`](#getvault-address-vaultid-) - [`getVaults({ cursor, limit, sortBy, sortOrder })`](#getvaults-cursor-limit-sortby-sortorder-) + - [`vaultedTransfer({ recipient, quantity, lockLengthMs, revokable })`](#vaultedtransfer-recipient-quantity-locklengthms-revokable-) + - [`revokeVault({ recipient, vaultId })`](#revokevault-recipient-vaultid-) + - [`createVault({ lockLengthMs, quantity })`](#createvault-locklengthms-quantity-) + - [`extendVault({ vaultId, extendLengthMs })`](#extendvault-vaultid-extendlengthms-) + - [`increaseVault({ vaultId, quantity })`](#increasevault-vaultid-quantity-) - [Gateways](#gateways) - [`getGateway({ address })`](#getgateway-address-) - [`getGateways({ cursor, limit, sortBy, sortOrder })`](#getgateways-cursor-limit-sortby-sortorder-) @@ -89,6 +94,9 @@ This is the home of [ar.io] SDK. This SDK provides functionality for interacting - [`transfer({ target })`](#transfer-target-) - [`setController({ controller })`](#setcontroller-controller-) - [`removeController({ controller })`](#removecontroller-controller-) + - [`setBaseNameRecord({ transactionId, ttlSeconds })`](#setbasenamerecord-transactionid-ttlseconds-) + - [`setUndernameRecord({ undername, transactionId, ttlSeconds })`](#setundernamerecord-undername-transactionid-ttlseconds-) + - [`removeUndernameRecord({ undername })`](#removeundernamerecord-undername-) - [`setRecord({ undername, transactionId, ttlSeconds })`](#setrecord-undername-transactionid-ttlseconds-) - [`removeRecord({ undername })`](#removerecord-undername-) - [`setName({ name })`](#setname-name-) @@ -511,6 +519,79 @@ const vaults = await ario.getVaults({ +#### `vaultedTransfer({ recipient, quantity, lockLengthMs, revokable })` + +Transfers `mARIO` to the designated `recipient` address and locks the balance for the specified `lockLengthMs` milliseconds. The `revokable` flag determines if the vaulted transfer can be revoked by the sender. + +_Note: Requires `signer` to be provided on `ARIO.init` to sign the transaction._ + +```typescript +const ario = ARIO.init({ signer: new ArweaveSigner(jwk) }); +const { id: txId } = await ario.vaultedTransfer( + { + recipient: '-5dV7nk7waR8v4STuwPnTck1zFVkQqJh5K9q9Zik4Y5', + quantity: new ARIOToken(1000).toMARIO(), + lockLengthMs: 1000 * 60 * 60 * 24 * 365, // 1 year + revokable: true, + }, + // optional additional tags + { tags: [{ name: 'App-Name', value: 'My-Awesome-App' }] }, +); +``` + +#### `revokeVault({ recipient, vaultId })` + +Revokes a vaulted transfer by the recipient address and vault ID. Only the sender of the vaulted transfer can revoke it. + +_Note: Requires `signer` to be provided on `ARIO.init` to sign the transaction._ + +```typescript +const ario = ARIO.init({ signer: new ArweaveSigner(jwk) }); +const { id: txId } = await ario.revokeVault({ + recipient: '-5dV7nk7waR8v4STuwPnTck1zFVkQqJh5K9q9Zik4Y5', + vaultId: 'IPdwa3Mb_9pDD8c2IaJx6aad51Ss-_TfStVwBuhtXMs', +}); +``` + +#### `createVault({ lockLengthMs, quantity })` + +Creates a vault for the specified `quantity` of mARIO from the signer's balance and locks it for the specified `lockLengthMs` milliseconds. + +```typescript +const ario = ARIO.init({ signer: new ArweaveSigner(jwk) }); + +const { id: txId } = await ario.createVault({ + lockLengthMs: 1000 * 60 * 60 * 24 * 365, // 1 year + quantity: new ARIOToken(1000).toMARIO(), +}); +``` + +#### `extendVault({ vaultId, extendLengthMs })` + +Extends the lock length of a signer's vault by the specified `extendLengthMs` milliseconds. + +```typescript +const ario = ARIO.init({ signer: new ArweaveSigner(jwk) }); + +const { id: txId } = await ario.extendVault({ + vaultId: 'vaultIdOne', + extendLengthMs: 1000 * 60 * 60 * 24 * 365, // 1 year +}); +``` + +#### `increaseVault({ vaultId, quantity })` + +Increases the balance of a signer's vault by the specified `quantity` of mARIO. + +```typescript +const ario = ARIO.init({ signer: new ArweaveSigner(jwk) }); + +const { id: txId } = await ario.increaseVault({ + vaultId: 'vaultIdOne', + quantity: new ARIOToken(1000).toMARIO(), +}); +``` + ### Gateways #### `getGateway({ address })` @@ -2024,9 +2105,70 @@ const { id: txId } = await ant.removeController( ); ``` +#### `setBaseNameRecord({ transactionId, ttlSeconds })` + +Adds or updates the base name record for the ANT. This is the top level name of the ANT (e.g. ardrive.ar.io) + +_Note: Requires `signer` to be provided on `ANT.init` to sign the transaction._ + +```typescript +// get the ant for the base name +const arnsRecord = await ario.getArNSRecord({ name: 'ardrive' }); +const ant = await ANT.init({ processId: arnsName.processId }); +const { id: txId } = await ant.setBaseNameRecord({ + transactionId: '432l1cy0aksiL_x9M359faGzM_yjralacHIUo8_nQXM', + ttlSeconds: 3600, +}); + +// ardrive.ar.io will now resolve to the provided 432l1cy0aksiL_x9M359faGzM_yjralacHIUo8_nQXM transaction id +``` + +#### `setUndernameRecord({ undername, transactionId, ttlSeconds })` + +Adds or updates an undername record for the ANT. An undername is appended to the base name of the ANT (e.g. dapp_ardrive.ar.io) + +_Note: Requires `signer` to be provided on `ANT.init` to sign the transaction._ + +> Records, or `undernames` are configured with the `transactionId` - the arweave transaction id the record resolves - and `ttlSeconds`, the Time To Live in the cache of client applications. + +```typescript +const arnsRecord = await ario.getArNSRecord({ name: 'ardrive' }); +const ant = await ANT.init({ processId: arnsName.processId }); +const { id: txId } = await ant.setUndernameRecord( + { + undername: 'dapp', + transactionId: '432l1cy0aksiL_x9M359faGzM_yjralacHIUo8_nQXM', + ttlSeconds: 900, + }, + // optional additional tags + { tags: [{ name: 'App-Name', value: 'My-Awesome-App' }] }, +); + +// dapp_ardrive.ar.io will now resolve to the provided 432l1cy0aksiL_x9M359faGzM_yjralacHIUo8_nQXM transaction id +``` + +#### `removeUndernameRecord({ undername })` + +Removes an undername record from the ANT process. + +_Note: Requires `signer` to be provided on `ANT.init` to sign the transaction._ + +```typescript +const { id: txId } = await ant.removeUndernameRecord( + { undername: 'dapp' }, + // optional additional tags + { tags: [{ name: 'App-Name', value: 'My-Awesome-App' }] }, +); + +// dapp_ardrive.ar.io will no longer resolve to the provided transaction id +``` + #### `setRecord({ undername, transactionId, ttlSeconds })` -Updates or creates a record in the ANT process. +> [!WARNING] +> Deprecated: Use `setBaseNameRecord` or `setUndernameRecord` instead. + +Adds or updates a record for the ANT process. The `undername` parameter is used to specify the record name. Use `@` for the base name record. _Note: Requires `signer` to be provided on `ANT.init` to sign the transaction._ @@ -2046,16 +2188,23 @@ const { id: txId } = await ant.setRecord( #### `removeRecord({ undername })` +> [!WARNING] +> Deprecated: Use `removeUndernameRecord` instead. + Removes a record from the ANT process. _Note: Requires `signer` to be provided on `ANT.init` to sign the transaction._ ```typescript +const arnsRecord = await ario.getArNSRecord({ name: 'ardrive' }); +const ant = await ANT.init({ processId: arnsName.processId }); const { id: txId } = await ant.removeRecord( - { undername: 'remove-domemain' }, + { undername: 'dapp' }, // optional additional tags { tags: [{ name: 'App-Name', value: 'My-Awesome-App' }] }, ); + +// dapp_ardrive.ar.io will no longer resolve to the provided transaction id ``` #### `setName({ name })` diff --git a/package.json b/package.json index 524d356d..96658a98 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@ar.io/sdk", - "version": "3.3.1", + "version": "3.4.0-alpha.4", "repository": { "type": "git", "url": "git+https://github.com/ar-io/ar-io-sdk.git" diff --git a/src/cli/cli.ts b/src/cli/cli.ts index 519ac1b0..64beaea6 100644 --- a/src/cli/cli.ts +++ b/src/cli/cli.ts @@ -21,6 +21,10 @@ import { program } from 'commander'; import { AOProcess, AoMessageResult, spawnANT } from '../node/index.js'; import { mARIOToken } from '../types/token.js'; import { version } from '../version.js'; +import { + setAntBaseNameCLICommand, + setAntRecordCLICommand, +} from './commands/antCommands.js'; import { buyRecordCLICommand, extendLeaseCLICommand, @@ -64,7 +68,14 @@ import { listArNSReturnedNames, listGateways, } from './commands/readCommands.js'; -import { transfer } from './commands/transfer.js'; +import { + createVaultCLICommand, + extendVaultCLICommand, + increaseVaultCLICommand, + revokeVaultCLICommand, + transferCLICommand, + vaultedTransferCLICommand, +} from './commands/transfer.js'; import { addressAndVaultIdOptions, antStateOptions, @@ -81,9 +92,12 @@ import { paginationAddressOptions, paginationOptions, redelegateStakeOptions, + setAntBaseNameOptions, + setAntUndernameOptions, tokenCostOptions, transferOptions, updateGatewaySettingsOptions, + vaultedTransferOptions, writeActionOptions, } from './options.js'; import { @@ -424,7 +438,42 @@ makeCommand({ name: 'transfer', description: 'Transfer ARIO to another address', options: transferOptions, - action: transfer, + action: transferCLICommand, +}); + +makeCommand({ + name: 'vaulted-transfer', + description: 'Transfer ARIO to another address into a locked vault', + options: vaultedTransferOptions, + action: vaultedTransferCLICommand, +}); + +makeCommand({ + name: 'revoke-vault', + description: 'Revoke a vaulted transfer as the controller', + options: [...writeActionOptions, optionMap.vaultId, optionMap.recipient], + action: revokeVaultCLICommand, +}); + +makeCommand({ + name: 'create-vault', + description: 'Create a locked vault with balance from the sender', + options: [...writeActionOptions, optionMap.lockLengthMs, optionMap.quantity], + action: createVaultCLICommand, +}); + +makeCommand({ + name: 'extend-vault', + description: 'Extend the lock length of a vault as the recipient', + options: [...writeActionOptions, optionMap.vaultId, optionMap.extendLengthMs], + action: extendVaultCLICommand, +}); + +makeCommand({ + name: 'increase-vault', + description: 'Increase the balance of a locked vault as the recipient', + options: [...writeActionOptions, optionMap.vaultId, optionMap.quantity], + action: increaseVaultCLICommand, }); makeCommand({ @@ -719,45 +768,26 @@ makeCommand({ }, }); -makeCommand< - ProcessIdWriteActionCLIOptions & { - undername?: string; - transactionId?: string; - ttlSeconds?: number; - } ->({ +makeCommand({ name: 'set-ant-record', - description: 'Set a record of an ANT process', - options: [ - optionMap.processId, - optionMap.undername, - optionMap.transactionId, - optionMap.ttlSeconds, - ...writeActionOptions, - ], - action: async (options) => { - const ttlSeconds = options.ttlSeconds ?? 3600; - const undername = requiredStringFromOptions(options, 'undername'); - const transactionId = requiredStringFromOptions(options, 'transactionId'); + description: + 'Set a record of an ANT process. Deprecated: use set-ant-base-name and set-ant-undername', + options: setAntUndernameOptions, + action: setAntRecordCLICommand, +}); - await assertConfirmationPrompt( - `Are you sure you want to set this record?\n${JSON.stringify( - { undername, transactionId, ttlSeconds }, - null, - 2, - )}`, - options, - ); +makeCommand({ + name: 'set-ant-base-name', + description: 'Set the base name of an ANT process', + options: setAntBaseNameOptions, + action: setAntBaseNameCLICommand, +}); - return writeANTFromOptions(options).setRecord( - { - undername, - transactionId, - ttlSeconds, - }, - writeActionTagsFromOptions(options), - ); - }, +makeCommand({ + name: 'set-ant-undername', + description: 'Set an undername of an ANT process', + options: setAntUndernameOptions, + action: setAntRecordCLICommand, }); makeCommand({ diff --git a/src/cli/commands/antCommands.ts b/src/cli/commands/antCommands.ts new file mode 100644 index 00000000..f8747167 --- /dev/null +++ b/src/cli/commands/antCommands.ts @@ -0,0 +1,116 @@ +/** + * Copyright (C) 2022-2024 Permanent Data Solutions, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { + AoANTSetBaseNameRecordParams, + AoANTSetUndernameRecordParams, +} from '../../types/ant.js'; +import { CLIWriteOptionsFromAoAntParams } from '../types.js'; +import { + assertConfirmationPrompt, + defaultTtlSecondsCLI, + requiredStringFromOptions, + writeANTFromOptions, + writeActionTagsFromOptions, +} from '../utils.js'; + +/** @deprecated -- use set-ant-base-name and set-ant-undername */ +export async function setAntRecordCLICommand( + o: CLIWriteOptionsFromAoAntParams, +) { + const ttlSeconds = +(o.ttlSeconds ?? defaultTtlSecondsCLI); + const undername = requiredStringFromOptions(o, 'undername'); + const transactionId = requiredStringFromOptions(o, 'transactionId'); + + const writeAnt = writeANTFromOptions(o); + + if (!o.skipConfirmation) { + await assertConfirmationPrompt( + `Are you sure you want to set this record on the ANT process ${writeAnt.processId}?\n${JSON.stringify( + { undername, transactionId, ttlSeconds }, + null, + 2, + )}`, + o, + ); + } + + return writeANTFromOptions(o).setRecord( + { + undername, + transactionId, + ttlSeconds, + }, + writeActionTagsFromOptions(o), + ); +} + +export async function setAntBaseNameCLICommand( + o: CLIWriteOptionsFromAoAntParams, +) { + const ttlSeconds = +(o.ttlSeconds ?? defaultTtlSecondsCLI); + const transactionId = requiredStringFromOptions(o, 'transactionId'); + + const writeAnt = writeANTFromOptions(o); + + if (!o.skipConfirmation) { + await assertConfirmationPrompt( + `Are you sure you want to set this base name on the ANT process ${writeAnt.processId}?\n${JSON.stringify( + { transactionId, ttlSeconds }, + null, + 2, + )}`, + o, + ); + } + + return writeANTFromOptions(o).setBaseNameRecord( + { + transactionId, + ttlSeconds, + }, + writeActionTagsFromOptions(o), + ); +} + +export async function setAntUndernameCLICommand( + o: CLIWriteOptionsFromAoAntParams, +) { + const ttlSeconds = +(o.ttlSeconds ?? defaultTtlSecondsCLI); + const undername = requiredStringFromOptions(o, 'undername'); + const transactionId = requiredStringFromOptions(o, 'transactionId'); + + const writeAnt = writeANTFromOptions(o); + + if (!o.skipConfirmation) { + await assertConfirmationPrompt( + `Are you sure you want to set this undername on the ANT process ${writeAnt.processId}?\n${JSON.stringify( + { undername, transactionId, ttlSeconds }, + null, + 2, + )}`, + o, + ); + } + + return writeANTFromOptions(o).setUndernameRecord( + { + undername, + transactionId, + ttlSeconds, + }, + writeActionTagsFromOptions(o), + ); +} diff --git a/src/cli/commands/transfer.ts b/src/cli/commands/transfer.ts index c7619c25..b1638970 100644 --- a/src/cli/commands/transfer.ts +++ b/src/cli/commands/transfer.ts @@ -13,17 +13,33 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { TransferCLIOptions } from '../types.js'; +import { + AoCreateVaultParams, + AoExtendVaultParams, + AoIncreaseVaultParams, + AoRevokeVaultParams, + AoVaultedTransferParams, +} from '../../types/io.js'; +import { + CLIWriteOptionsFromAoParams, + JsonSerializable, + TransferCLIOptions, +} from '../types.js'; import { assertEnoughMARIOBalance, + assertLockLengthInRange, confirmationPrompt, formatARIOWithCommas, + formatMARIOToARIOWithCommas, + requiredMARIOFromOptions, + requiredPositiveIntegerFromOptions, + requiredStringFromOptions, requiredTargetAndQuantityFromOptions, writeARIOFromOptions, writeActionTagsFromOptions, } from '../utils.js'; -export async function transfer(options: TransferCLIOptions) { +export async function transferCLICommand(options: TransferCLIOptions) { const { target, arioQuantity } = requiredTargetAndQuantityFromOptions(options); const { ario, signerAddress } = writeARIOFromOptions(options); @@ -59,3 +75,210 @@ export async function transfer(options: TransferCLIOptions) { return output; } + +export async function vaultedTransferCLICommand( + o: CLIWriteOptionsFromAoParams, +): Promise { + const mARIOQuantity = requiredMARIOFromOptions(o, 'quantity'); + const recipient = requiredStringFromOptions(o, 'recipient'); + const { ario, signerAddress } = writeARIOFromOptions(o); + const lockLengthMs = requiredPositiveIntegerFromOptions(o, 'lockLengthMs'); + assertLockLengthInRange(lockLengthMs); + + if (!o.skipConfirmation) { + await assertEnoughMARIOBalance({ + ario, + address: signerAddress, + mARIOQuantity, + }); + + const confirm = await confirmationPrompt( + `Are you sure you want transfer ${formatMARIOToARIOWithCommas(mARIOQuantity)} ARIO to ${recipient}, locked in a ${o.revokable ? '' : 'non-'}revokable vault for ${lockLengthMs}ms?`, + ); + if (!confirm) { + return { message: 'Transfer aborted by user' }; + } + } + + const result = await ario.vaultedTransfer( + { + recipient, + quantity: mARIOQuantity, + lockLengthMs, + revokable: o.revokable, + }, + writeActionTagsFromOptions(o), + ); + + const output = { + senderAddress: signerAddress, + transferResult: result, + message: `Successfully vaulted transferred ${formatMARIOToARIOWithCommas(mARIOQuantity)} ARIO to ${recipient}`, + }; + + return output; +} + +export async function revokeVaultCLICommand( + o: CLIWriteOptionsFromAoParams, +): Promise { + const { ario, signerAddress } = writeARIOFromOptions(o); + const vaultId = requiredStringFromOptions(o, 'vaultId'); + const recipient = requiredStringFromOptions(o, 'recipient'); + + if (!o.skipConfirmation) { + const vault = await ario.getVault({ vaultId, address: recipient }); + if (!vault) { + throw new Error( + `Vault for recipient '${recipient}' with vault id '${vaultId}' not found`, + ); + } + + const confirm = await confirmationPrompt( + `Are you sure you want to revoke vault with id ${vaultId} from ${recipient}?`, + ); + if (!confirm) { + return { message: 'Revoke aborted by user' }; + } + } + + const result = await ario.revokeVault( + { + vaultId, + recipient, + }, + writeActionTagsFromOptions(o), + ); + + const output = { + senderAddress: signerAddress, + transferResult: result, + message: `Successfully revoked vault with id ${vaultId}`, + }; + + return output; +} + +export async function createVaultCLICommand( + o: CLIWriteOptionsFromAoParams, +): Promise { + const mARIOQuantity = requiredMARIOFromOptions(o, 'quantity'); + const { ario, signerAddress } = writeARIOFromOptions(o); + const lockLengthMs = requiredPositiveIntegerFromOptions(o, 'lockLengthMs'); + assertLockLengthInRange(lockLengthMs); + + if (!o.skipConfirmation) { + await assertEnoughMARIOBalance({ + ario, + address: signerAddress, + mARIOQuantity, + }); + + const confirm = await confirmationPrompt( + `Are you sure you want to create a vault with ${formatMARIOToARIOWithCommas(mARIOQuantity)} ARIO, locked for ${lockLengthMs}ms?`, + ); + if (!confirm) { + return { message: 'Vault creation aborted by user' }; + } + } + + const result = await ario.createVault( + { + quantity: mARIOQuantity, + lockLengthMs, + }, + writeActionTagsFromOptions(o), + ); + + const output = { + senderAddress: signerAddress, + transferResult: result, + message: `Successfully created vault with ${formatMARIOToARIOWithCommas(mARIOQuantity)} ARIO`, + }; + + return output; +} + +export async function extendVaultCLICommand( + o: CLIWriteOptionsFromAoParams, +) { + const { ario, signerAddress } = writeARIOFromOptions(o); + const vaultId = requiredStringFromOptions(o, 'vaultId'); + const extendLengthMs = requiredPositiveIntegerFromOptions( + o, + 'extendLengthMs', + ); + assertLockLengthInRange(extendLengthMs, false); + + if (!o.skipConfirmation) { + const vault = await ario.getVault({ vaultId, address: signerAddress }); + if (!vault) { + throw new Error( + `Vault for signer '${signerAddress}' with vault id '${vaultId}' not found`, + ); + } + + const confirm = await confirmationPrompt( + `Are you sure you want to extend vault with id ${vaultId} for ${extendLengthMs}ms?`, + ); + if (!confirm) { + return { message: 'Vault extension aborted by user' }; + } + } + + const result = await ario.extendVault( + { + vaultId, + extendLengthMs, + }, + writeActionTagsFromOptions(o), + ); + + const output = { + senderAddress: signerAddress, + transferResult: result, + message: `Successfully extended vault with id ${vaultId}`, + }; + + return output; +} + +export async function increaseVaultCLICommand( + o: CLIWriteOptionsFromAoParams, +) { + const mARIOQuantity = requiredMARIOFromOptions(o, 'quantity'); + const { ario, signerAddress } = writeARIOFromOptions(o); + const vaultId = requiredStringFromOptions(o, 'vaultId'); + + if (!o.skipConfirmation) { + const vault = await ario.getVault({ vaultId, address: signerAddress }); + if (!vault) { + throw new Error( + `Vault for signer '${signerAddress}' with vault id '${vaultId}' not found`, + ); + } + + const confirm = await confirmationPrompt( + `Are you sure you want to increase vault with id ${vaultId} by ${formatMARIOToARIOWithCommas(mARIOQuantity)} ARIO?`, + ); + if (!confirm) { + return { message: 'Vault increase aborted by user' }; + } + } + + const result = await ario.increaseVault( + { + vaultId, + quantity: mARIOQuantity, + }, + writeActionTagsFromOptions(o), + ); + + const output = { + senderAddress: signerAddress, + transferResult: result, + message: `Successfully increased vault with id ${vaultId} by ${formatMARIOToARIOWithCommas(mARIOQuantity)} ARIO`, + }; + + return output; +} diff --git a/src/cli/options.ts b/src/cli/options.ts index bc2e99af..efe9f4e8 100644 --- a/src/cli/options.ts +++ b/src/cli/options.ts @@ -243,6 +243,24 @@ export const optionMap = { description: 'Where to fund the action from. e.g. "balance", "stakes", or "any', }, + revokable: { + alias: '--revokable', + description: + 'Whether the vaulted transfer is revokable by the sender. Defaults to false', + type: 'boolean', + }, + lockLengthMs: { + alias: '--lock-length-ms ', + description: 'The length of time in milliseconds to lock the vault for', + }, + extendLengthMs: { + alias: '--extend-length-ms ', + description: 'The length of time in milliseconds to extend the vault for', + }, + recipient: { + alias: '--recipient ', + description: 'The recipient to interact with', + }, }; export const walletOptions = [ @@ -303,6 +321,14 @@ export const transferOptions = [ optionMap.target, ]; +export const vaultedTransferOptions = [ + ...writeActionOptions, + optionMap.quantity, + optionMap.recipient, + optionMap.lockLengthMs, + optionMap.revokable, +]; + export const operatorStakeOptions = [ ...writeActionOptions, optionMap.operatorStake, @@ -356,3 +382,15 @@ export const antStateOptions = [ optionMap.controllers, optionMap.ttlSeconds, ]; + +export const setAntBaseNameOptions = [ + optionMap.processId, + optionMap.transactionId, + optionMap.ttlSeconds, + ...writeActionOptions, +]; + +export const setAntUndernameOptions = [ + ...setAntBaseNameOptions, + optionMap.undername, +]; diff --git a/src/cli/types.ts b/src/cli/types.ts index aa604bf3..ba43ea14 100644 --- a/src/cli/types.ts +++ b/src/cli/types.ts @@ -80,6 +80,10 @@ export type CLIReadOptionsFromAoParams = CLIOptionsFromAoParams & export type CLIWriteOptionsFromAoParams = WriteActionCLIOptions & CLIOptionsFromAoParams; +export type CLIWriteOptionsFromAoAntParams = CLIWriteOptionsFromAoParams< + T & { processId: string } +>; + export type PaginationCLIOptions = GlobalCLIOptions & CLIOptionsFromAoParams; diff --git a/src/cli/utils.ts b/src/cli/utils.ts index 7ac6295c..aecc1ade 100644 --- a/src/cli/utils.ts +++ b/src/cli/utils.ts @@ -71,6 +71,8 @@ import { WriteActionCLIOptions, } from './types.js'; +export const defaultTtlSecondsCLI = 3600; + export function stringifyJsonForCLIDisplay( json: JsonSerializable | unknown, ): string { @@ -543,6 +545,13 @@ export function writeANTFromOptions( }); } +export function booleanFromOptions( + options: O, + key: string, +): boolean { + return !!options[key]; +} + export function requiredStringFromOptions( options: O, key: string, @@ -605,7 +614,10 @@ export function getANTStateFromOptions( ticker: options.ticker, name: options.name, keywords: options.keywords, - ttlSeconds: options.ttlSeconds !== undefined ? +options.ttlSeconds : 3600, + ttlSeconds: + options.ttlSeconds !== undefined + ? +options.ttlSeconds + : defaultTtlSecondsCLI, }); } @@ -648,3 +660,26 @@ export function fundFromFromOptions< } return o.fundFrom ?? 'balance'; } + +export function assertLockLengthInRange( + lockLengthMs: number, + assertMin = true, // extend-vault has no min lock length +) { + const minLockLengthMs = 1209600000; // 14 days + const maxLockLengthMs = 378432000000; // ~12 years + + if (lockLengthMs > maxLockLengthMs) { + throw new Error( + `Lock length must be at most 12 years (378432000000 ms). Provided lock length: ${lockLengthMs} ms`, + ); + } + if (!assertMin) { + return; + } + + if (lockLengthMs < minLockLengthMs) { + throw new Error( + `Lock length must be at least 14 days (1209600000 ms). Provided lock length: ${lockLengthMs} ms`, + ); + } +} diff --git a/src/common/ant.ts b/src/common/ant.ts index f9d0c187..3dcdd1cc 100644 --- a/src/common/ant.ts +++ b/src/common/ant.ts @@ -27,6 +27,8 @@ import { AoANTInfo, AoANTRead, AoANTRecord, + AoANTSetBaseNameRecordParams, + AoANTSetUndernameRecordParams, AoANTState, AoANTWrite, } from '../types/ant.js'; @@ -69,6 +71,7 @@ export class ANT { export class AoANTReadable implements AoANTRead { protected process: AOProcess; + public readonly processId: string; private strict: boolean; constructor(config: ANTConfigOptionalStrict) { @@ -82,6 +85,8 @@ export class AoANTReadable implements AoANTRead { } else { throw new InvalidContractConfigurationError(); } + + this.processId = this.process.processId; } async getState( @@ -386,25 +391,16 @@ export class AoANTWriteable extends AoANTReadable implements AoANTWrite { } /** + * Sets the transactionId and ttlSeconds of a record (for updating the top level name, use undername "@".) + * + * @deprecated Use setUndernameRecord instead for undernames, and setBaseNameRecord instead for the top level name (e.g. "@") * @param undername @type {string} The record you want to set the transactionId and ttlSeconds of. * @param transactionId @type {string} The transactionId of the record. * @param ttlSeconds @type {number} The time to live of the record. * @returns {Promise} The result of the interaction. - * @example - * ```ts - * ant.setController({ controller: "fGht8v4STuwPnTck1zFVkQqJh5K9q9Zik4Y5-5dV7nk" }); - * ``` */ async setRecord( - { - undername, - transactionId, - ttlSeconds, - }: { - undername: string; - transactionId: string; - ttlSeconds: number; - }, + { undername, transactionId, ttlSeconds }: AoANTSetUndernameRecordParams, options?: WriteOptions, ): Promise { return this.process.send({ @@ -420,11 +416,83 @@ export class AoANTWriteable extends AoANTReadable implements AoANTWrite { } /** + * Sets the top level name of the ANT. This is the name that will be used to resolve the ANT (e.g. ardrive.ar.io) + * + * @param transactionId @type {string} The transactionId of the record. + * @param ttlSeconds @type {number} The time to live of the record. + * @returns {Promise} The result of the interaction. + * @example + * ```ts + * ant.setBaseNameRecord({ transactionId: "432l1cy0aksiL_x9M359faGzM_yjralacHIUo8_nQXM", ttlSeconds: 100 }); // ardrive.ar.io will resolve to the provided transaction id and be cached for 100 seconds by clients + * ``` + */ + async setBaseNameRecord( + { transactionId, ttlSeconds }: AoANTSetBaseNameRecordParams, + options?: WriteOptions, + ): Promise { + return this.setRecord( + { + transactionId, + ttlSeconds, + undername: '@', + }, + options, + ); + } + + /** + * Adds or updates an undername of the ANT. An undername is appended to the base name of the ANT (e.g. ardrive.ar.io) to form a fully qualified name (e.g. dapp_ardrive.ar.io) + * + * @param undername @type {string} The undername of the ANT. + * @param transactionId @type {string} The transactionId of the record. + * @param ttlSeconds @type {number} The time to live of the record. + * @returns {Promise} The result of the interaction. + * @example + * ```ts + * ant.setUndernameRecord({ undername: "dapp", transactionId: "432l1cy0aksiL_x9M359faGzM_yjralacHIUo8_nQXM", ttlSeconds: 100 }); // dapp_ardrive.ar.io will resolve to the provided transaction id and be cached for 100 seconds by clients + * ``` + */ + async setUndernameRecord( + { undername, transactionId, ttlSeconds }: AoANTSetUndernameRecordParams, + options?: WriteOptions, + ): Promise { + return this.setRecord( + { + undername, + transactionId, + ttlSeconds, + }, + options, + ); + } + + /** + * Removes an undername from the ANT. This will remove the undername from the ANT. + * + * @param undername @type {string} The undername you want to remove. + * @returns {Promise} The result of the interaction. + * @example + * ```ts + * ant.removeUndernameRecord({ undername: "dapp" }); // removes dapp_ardrive.ar.io + * ``` + */ + async removeUndernameRecord({ + undername, + }: { + undername: string; + }): Promise { + return this.removeRecord({ undername }); + } + + /** + * Removes a record from the ANT. This will remove the record from the ANT. If '@' is provided, the top level name will be removed. + * + * @deprecated Use removeUndernameRecord instead. * @param undername @type {string} The record you want to remove. * @returns {Promise} The result of the interaction. * @example * ```ts - * ant.removeRecord({ subDomain: "shorts" }); + * ant.removeRecord({ undername: "dapp" }); // removes dapp_ardrive.ar.io * ``` */ async removeRecord( @@ -446,6 +514,8 @@ export class AoANTWriteable extends AoANTReadable implements AoANTWrite { } /** + * Sets the ticker of the ANT. This is the abbreviation displayed in ecosystem apps. + * * @param ticker @type {string} Sets the ANT Ticker. * @returns {Promise} The result of the interaction. * @example @@ -467,6 +537,8 @@ export class AoANTWriteable extends AoANTReadable implements AoANTWrite { }); } /** + * Sets the name of the ANT. This is the display name of the ANT. This is NOT the base name record. + * * @param name @type {string} Sets the Name of the ANT. * @returns {Promise} The result of the interaction. * @example @@ -489,6 +561,8 @@ export class AoANTWriteable extends AoANTReadable implements AoANTWrite { } /** + * Sets the description of the ANT. This is the description of the ANT displayed in ecosystem apps. + * * @param description @type {string} Sets the ANT Description. * @returns {Promise} The result of the interaction. * @example @@ -511,6 +585,8 @@ export class AoANTWriteable extends AoANTReadable implements AoANTWrite { } /** + * Sets the keywords of the ANT. This is the keywords of the ANT displayed in ecosystem apps. + * * @param keywords @type {string[]} Sets the ANT Keywords. * @returns {Promise} The result of the interaction. * @example @@ -533,6 +609,8 @@ export class AoANTWriteable extends AoANTReadable implements AoANTWrite { } /** + * Sets the logo of the ANT. This is the logo of the ANT displayed in ecosystem apps. Additionally, this logo is displayed for any primary names affiliated with the ANT. + * * @param txId @type {string} - Arweave transaction id of the logo we want to set * @param options @type {WriteOptions} - additional options to add to the write interaction (optional) * @returns {Promise} The result of the interaction. @@ -556,6 +634,9 @@ export class AoANTWriteable extends AoANTReadable implements AoANTWrite { } /** + * Releases an ArNS name associated with the ANT. This will release the name to the public and allow anyone to register it. All primary names must be removed before the name can be released. + * + * * @param name @type {string} The name you want to release. The name will be put up for as a recently returned name on the ARIO contract. 50% of the winning bid will be distributed to the ANT owner at the time of purchase. If no purchase in the recently returned name period (14 epochs), the name will be released and can be reregistered by anyone. * @param arioProcessId @type {string} The processId of the ARIO contract. This is where the ANT will send the message to release the name. * @returns {Promise} The result of the interaction. @@ -581,7 +662,8 @@ export class AoANTWriteable extends AoANTReadable implements AoANTWrite { } /** - * Sends a message to the ARIO contract to reassign the name to a new ANT. This can only be done by the current owner of the ANT. + * Sends a message to the ARIO contract to reassign the the base ArNS name to a new ANT. This can only be done by the current owner of the ANT. + * * @param name @type {string} The name you want to reassign. * @param arioProcessId @type {string} The processId of the ARIO contract. * @param antProcessId @type {string} The processId of the ANT contract. @@ -614,6 +696,15 @@ export class AoANTWriteable extends AoANTReadable implements AoANTWrite { /** * Approves a primary name request for a given name or address. + * + * @param name @type {string} The name you want to approve. + * @param address @type {WalletAddress} The address you want to approve. + * @param arioProcessId @type {string} The processId of the ARIO contract. + * @returns {Promise} The result of the interaction. + * @example + * ```ts + * ant.approvePrimaryNameRequest({ name: "ardrive", address: "U7RXcpaVShG4u9nIcPVmm2FJSM5Gru9gQCIiRaIPV7f", arioProcessId: ARIO_TESTNET_PROCESS_ID }); // approves the request for ardrive.ar.io to be registered by the address + * ``` */ async approvePrimaryNameRequest( { @@ -636,6 +727,18 @@ export class AoANTWriteable extends AoANTReadable implements AoANTWrite { }); } + /** + * Removes primary names from the ANT. This will remove the primary names associated with the base ArNS name controlled by this ANT. All primary names must be removed before the name can be released. + * + * @param names @type {string[]} The names you want to remove. + * @param arioProcessId @type {string} The processId of the ARIO contract. + * @param notifyOwners @type {boolean} Whether to notify the owners of the primary names. + * @returns {Promise} The result of the interaction. + * @example + * ```ts + * ant.removePrimaryNames({ names: ["ardrive", "dapp_ardrive"], arioProcessId: ARIO_TESTNET_PROCESS_ID, notifyOwners: true }); // removes the primary names and associated wallet addresses assigned to "ardrive" and "dapp_ardrive" + * ``` + */ async removePrimaryNames( { names, diff --git a/src/common/io.ts b/src/common/io.ts index 9a2f0b2c..1cd1cdf6 100644 --- a/src/common/io.ts +++ b/src/common/io.ts @@ -50,20 +50,25 @@ import { AoArNSPurchaseParams, AoArNSReservedNameDataWithName, AoBuyRecordParams, + AoCreateVaultParams, AoDelegation, AoEpochData, AoEpochSettings, AoExtendLeaseParams, + AoExtendVaultParams, AoGateway, AoGatewayDelegateWithAddress, AoGatewayRegistrySettings, AoGatewayVault, AoGetCostDetailsParams, AoIncreaseUndernameLimitParams, + AoIncreaseVaultParams, AoPaginatedAddressParams, AoRegistrationFees, + AoRevokeVaultParams, AoTokenCostParams, AoVaultData, + AoVaultedTransferParams, AoWalletVault, CostDetailsResult, DemandFactorSettings, @@ -770,6 +775,94 @@ export class ARIOWriteable extends ARIOReadable implements AoARIOWrite { }); } + async vaultedTransfer( + { + recipient, + quantity, + lockLengthMs, + revokable = false, + }: AoVaultedTransferParams, + options?: WriteOptions, + ): Promise { + const { tags = [] } = options || {}; + + return this.process.send({ + tags: [ + ...tags, + { name: 'Action', value: 'Vaulted-Transfer' }, + { name: 'Recipient', value: recipient }, + { name: 'Quantity', value: quantity.toString() }, + { name: 'Lock-Length', value: lockLengthMs.toString() }, + { name: 'Revokable', value: `${revokable}` }, + ], + signer: this.signer, + }); + } + + async revokeVault( + { vaultId, recipient }: AoRevokeVaultParams, + options?: WriteOptions, + ): Promise { + const { tags = [] } = options || {}; + return this.process.send({ + tags: [ + ...tags, + { name: 'Action', value: 'Revoke-Vault' }, + { name: 'Vault-Id', value: vaultId }, + { name: 'Recipient', value: recipient }, + ], + signer: this.signer, + }); + } + + async createVault( + { lockLengthMs, quantity }: AoCreateVaultParams, + options?: WriteOptions, + ): Promise { + const { tags = [] } = options || {}; + return this.process.send({ + tags: [ + ...tags, + { name: 'Action', value: 'Create-Vault' }, + { name: 'Lock-Length', value: lockLengthMs.toString() }, + { name: 'Quantity', value: quantity.toString() }, + ], + signer: this.signer, + }); + } + + async extendVault( + { vaultId, extendLengthMs }: AoExtendVaultParams, + options?: WriteOptions, + ): Promise { + const { tags = [] } = options || {}; + return this.process.send({ + tags: [ + ...tags, + { name: 'Action', value: 'Extend-Vault' }, + { name: 'Vault-Id', value: vaultId }, + { name: 'Extend-Length', value: extendLengthMs.toString() }, + ], + signer: this.signer, + }); + } + + async increaseVault( + { vaultId, quantity }: AoIncreaseVaultParams, + options?: WriteOptions, + ): Promise { + const { tags = [] } = options || {}; + return this.process.send({ + tags: [ + ...tags, + { name: 'Action', value: 'Increase-Vault' }, + { name: 'Vault-Id', value: vaultId }, + { name: 'Quantity', value: quantity.toString() }, + ], + signer: this.signer, + }); + } + async joinNetwork( { operatorStake, diff --git a/src/types/ant.ts b/src/types/ant.ts index dc080556..d7b18d33 100644 --- a/src/types/ant.ts +++ b/src/types/ant.ts @@ -16,7 +16,7 @@ import { z } from 'zod'; import { ARWEAVE_TX_REGEX } from '../constants.js'; -import { AoMessageResult, WalletAddress, WriteOptions } from './common.js'; +import { AoWriteAction, WalletAddress } from './common.js'; /** * example error: @@ -181,6 +181,7 @@ export function isAoANTState(state: object): state is AoANTState { export type AntReadOptions = { strict?: boolean }; export interface AoANTRead { + processId: string; getState(opts?: AntReadOptions): Promise; getInfo(opts?: AntReadOptions): Promise; getRecord( @@ -202,88 +203,43 @@ export interface AoANTRead { } export interface AoANTWrite extends AoANTRead { - transfer( - { target }: { target: WalletAddress }, - options?: WriteOptions, - ): Promise; - addController( - { - controller, - }: { - controller: WalletAddress; - }, - options?: WriteOptions, - ): Promise; - removeController( - { - controller, - }: { - controller: WalletAddress; - }, - options?: WriteOptions, - ): Promise; - setRecord( - { - undername, - transactionId, - ttlSeconds, - }: { - undername: string; - transactionId: string; - ttlSeconds: number; - }, - options?: WriteOptions, - ): Promise; - removeRecord( - { undername }: { undername: string }, - options?: WriteOptions, - ): Promise; - setTicker( - { ticker }: { ticker: string }, - options?: WriteOptions, - ): Promise; - setDescription( - { description }: { description: string }, - options?: WriteOptions, - ): Promise; - setKeywords( - { keywords }: { keywords: string[] }, - options?: WriteOptions, - ): Promise; - setName( - { name }: { name: string }, - options?: WriteOptions, - ): Promise; - setLogo( - { txId }: { txId: string }, - options?: WriteOptions, - ): Promise; - releaseName( - { name, arioProcessId }: { name: string; arioProcessId: string }, - options?: WriteOptions, - ): Promise; - reassignName( - { - name, - arioProcessId, - antProcessId, - }: { name: string; arioProcessId: string; antProcessId: string }, - options?: WriteOptions, - ): Promise; - approvePrimaryNameRequest( - { - name, - address, - arioProcessId, - }: { name: string; address: WalletAddress; arioProcessId: string }, - options?: WriteOptions, - ): Promise; - removePrimaryNames( - { - names, - arioProcessId, - notifyOwners, - }: { names: string[]; arioProcessId: string; notifyOwners?: boolean }, - options?: WriteOptions, - ): Promise; + transfer: AoWriteAction<{ target: WalletAddress }>; + addController: AoWriteAction<{ controller: WalletAddress }>; + removeController: AoWriteAction<{ controller: WalletAddress }>; + /** @deprecated Use setUndernameRecord instead for undernames, and setBaseNameRecord instead for the top level name (e.g. "@") */ + setRecord: AoWriteAction; + removeRecord: AoWriteAction<{ undername: string }>; + setBaseNameRecord: AoWriteAction; + setUndernameRecord: AoWriteAction; + removeUndernameRecord: AoWriteAction<{ undername: string }>; + setTicker: AoWriteAction<{ ticker: string }>; + setDescription: AoWriteAction<{ description: string }>; + setKeywords: AoWriteAction<{ keywords: string[] }>; + setName: AoWriteAction<{ name: string }>; + setLogo: AoWriteAction<{ txId: string }>; + releaseName: AoWriteAction<{ name: string; arioProcessId: string }>; + reassignName: AoWriteAction<{ + name: string; + arioProcessId: string; + antProcessId: string; + }>; + approvePrimaryNameRequest: AoWriteAction<{ + name: string; + address: string; + arioProcessId: string; + }>; + removePrimaryNames: AoWriteAction<{ + names: string[]; + arioProcessId: string; + notifyOwners?: boolean; + }>; } + +export type AoANTSetBaseNameRecordParams = { + transactionId: string; + ttlSeconds: number; +}; + +export type AoANTSetUndernameRecordParams = AoANTSetBaseNameRecordParams & { + undername: string; +}; diff --git a/src/types/common.ts b/src/types/common.ts index f50d99e8..4ee71836 100644 --- a/src/types/common.ts +++ b/src/types/common.ts @@ -135,3 +135,9 @@ export interface AOContract { signer: AoSigner; }): Promise<{ id: string; result?: K }>; } + +/** utility type to ensure WriteOptions are appended to each parameter set */ +export type AoWriteAction = ( + params: P, + options?: WriteOptions, +) => Promise; diff --git a/src/types/io.ts b/src/types/io.ts index f1c48673..02ace298 100644 --- a/src/types/io.ts +++ b/src/types/io.ts @@ -20,6 +20,7 @@ import { AoPrimaryName, AoPrimaryNameRequest, AoRedelegationFeeInfo, + AoWriteAction, AtLeastOne, BlockHeight, ProcessId, @@ -455,6 +456,33 @@ export type AoIncreaseUndernameLimitParams = AoArNSPurchaseParams & { increaseCount: number; }; +export type AoVaultedTransferParams = { + recipient: WalletAddress; + quantity: mARIOToken | number; + lockLengthMs: number; + revokable?: boolean; +}; + +export type AoRevokeVaultParams = { + vaultId: TransactionId; + recipient: WalletAddress; +}; + +export type AoCreateVaultParams = { + quantity: mARIOToken | number; + lockLengthMs: number; +}; + +export type AoExtendVaultParams = { + vaultId: string; + extendLengthMs: number; +}; + +export type AoIncreaseVaultParams = { + vaultId: string; + quantity: mARIOToken | number; +}; + export type AoGatewayRegistrySettings = { delegates: { minStake: number; @@ -615,103 +643,50 @@ export interface AoARIORead { export interface AoARIOWrite extends AoARIORead { // write interactions - transfer( - { - target, - qty, - }: { - target: WalletAddress; - qty: number; - }, - options?: WriteOptions, - ): Promise; + transfer: AoWriteAction<{ target: WalletAddress; qty: number | mARIOToken }>; + vaultedTransfer: AoWriteAction; + revokeVault: AoWriteAction; + createVault: AoWriteAction; + extendVault: AoWriteAction; + increaseVault: AoWriteAction; + // TODO: these could be moved to a separate Gateways class that implements gateway specific interactions - joinNetwork( - params: AoJoinNetworkParams, - options?: WriteOptions, - ): Promise; - leaveNetwork(options?: WriteOptions): Promise; - updateGatewaySettings( - params: AoUpdateGatewaySettingsParams, - options?: WriteOptions, - ): Promise; - increaseOperatorStake( - params: { - increaseQty: number | mARIOToken; - }, - options?: WriteOptions, - ): Promise; - decreaseOperatorStake( - params: { - decreaseQty: number | mARIOToken; - instant?: boolean; - }, - options?: WriteOptions, - ): Promise; - delegateStake( - params: { - target: WalletAddress; - stakeQty: number | mARIOToken; - }, - options?: WriteOptions, - ): Promise; - decreaseDelegateStake( - params: { - target: WalletAddress; - decreaseQty: number | mARIOToken; - instant?: boolean; - }, - options?: WriteOptions, - ): Promise; - instantWithdrawal( - params: { - gatewayAddress?: WalletAddress; - vaultId: string; - }, - options?: WriteOptions, - ): Promise; - saveObservations( - params: { - reportTxId: TransactionId; - failedGateways: WalletAddress[]; - }, - options?: WriteOptions, - ): Promise; + joinNetwork: AoWriteAction; + leaveNetwork: (options?: WriteOptions) => Promise; + updateGatewaySettings: AoWriteAction; + increaseOperatorStake: AoWriteAction<{ increaseQty: number | mARIOToken }>; + decreaseOperatorStake: AoWriteAction<{ + decreaseQty: number | mARIOToken; + instant?: boolean; + }>; + delegateStake: AoWriteAction; + decreaseDelegateStake: AoWriteAction<{ + target: WalletAddress; + decreaseQty: number | mARIOToken; + instant?: boolean; + }>; + instantWithdrawal: AoWriteAction<{ + gatewayAddress?: WalletAddress; + vaultId: string; + }>; + saveObservations: AoWriteAction<{ + reportTxId: TransactionId; + failedGateways: WalletAddress[]; + }>; // END OF GATEWAY SPECIFIC INTERACTIONS - buyRecord( - params: AoBuyRecordParams, - options?: WriteOptions, - ): Promise; - upgradeRecord( - params: AoArNSPurchaseParams, - options?: WriteOptions, - ): Promise; - extendLease( - params: AoExtendLeaseParams, - options?: WriteOptions, - ): Promise; - increaseUndernameLimit( - params: AoIncreaseUndernameLimitParams, - options?: WriteOptions, - ): Promise; - cancelWithdrawal( - params: { - gatewayAddress?: WalletAddress; - vaultId: string; - }, - options?: WriteOptions, - ): Promise; - requestPrimaryName( - params: AoArNSPurchaseParams, - options?: WriteOptions, - ): Promise; - redelegateStake( - params: AoRedelegateStakeParams, - options?: WriteOptions, - ): Promise; + buyRecord: AoWriteAction; + upgradeRecord: AoWriteAction; + extendLease: AoWriteAction; + increaseUndernameLimit: AoWriteAction; + cancelWithdrawal: AoWriteAction<{ + gatewayAddress?: WalletAddress; + vaultId: string; + }>; + requestPrimaryName: AoWriteAction; + redelegateStake: AoWriteAction; } -// Typeguard functions +// Type-guard functions export function isProcessConfiguration( config: object, ): config is Required & Record { diff --git a/src/version.ts b/src/version.ts index f9e0a74f..70c79218 100644 --- a/src/version.ts +++ b/src/version.ts @@ -15,4 +15,4 @@ */ // AUTOMATICALLY GENERATED FILE - DO NOT TOUCH -export const version = '3.3.1'; +export const version = '3.4.0-alpha.4';