diff --git a/package-lock.json b/package-lock.json index 86482b8..1dbf448 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@nockbox/iris-sdk", - "version": "0.2.0", + "version": "0.3.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@nockbox/iris-sdk", - "version": "0.2.0", + "version": "0.3.0", "license": "MIT", "dependencies": { "@nockbox/iris-wasm": "0.2.0", diff --git a/package.json b/package.json index 65e20c1..e5aef5b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@nockbox/iris-sdk", - "version": "0.2.0", + "version": "0.3.0", "description": "TypeScript SDK for interacting with Iris wallet extension", "type": "module", "main": "./dist/index.js", diff --git a/src/constants.ts b/src/constants.ts index 3e41718..20b7f0d 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -22,6 +22,9 @@ export const PROVIDER_METHODS = { /** Sign a nockchain transaction */ SIGN_TX: 'nock_signTx', + + /** Estimate the network fee for a simple send (read-only, no approval popup) */ + ESTIMATE_TRANSACTION_FEE: 'nock_estimateTransactionFee', } as const; export type ProviderMethod = (typeof PROVIDER_METHODS)[keyof typeof PROVIDER_METHODS]; diff --git a/src/provider.ts b/src/provider.ts index cae3a11..81d811e 100644 --- a/src/provider.ts +++ b/src/provider.ts @@ -15,6 +15,8 @@ import type { SignMessageResponse, ConnectRequest, SendTransactionRequest, + EstimateTransactionFeeRequest, + EstimateTransactionFeeResponse, } from './types.js'; import { WalletNotInstalledError, UserRejectedError, RpcError, NoAccountError } from './errors.js'; import { PROVIDER_METHODS, RPC_API_VERSION } from './constants.js'; @@ -134,6 +136,37 @@ export class NockchainProvider { }); } + /** + * Estimate the network fee for a simple send without sending it. + * Read-only: requires an approved origin and unlocked wallet, but shows no approval popup. + * Requires API 1 (`nock_estimateTransactionFee` is not available on legacy API 0 wallets). + * + * The estimate is advisory: it depends on the wallet's current UTXO set and may + * drift slightly between estimation and an actual send. + * + * @param request - Recipient and amount in nicks + * @returns Promise resolving to the estimated fee in nicks + * @throws {NoAccountError} If no account is connected + * @throws {RpcError} If the RPC call fails (e.g. wallet locked, no UTXOs) + * + * @example + * ```typescript + * const { fee } = await provider.estimateTransactionFee({ to: recipient, amount }); + * ``` + */ + async estimateTransactionFee( + request: EstimateTransactionFeeRequest + ): Promise { + if (!this.isConnected) { + throw new NoAccountError(); + } + + return this.request({ + method: PROVIDER_METHODS.ESTIMATE_TRANSACTION_FEE, + params: request, + }); + } + /** * Sign an arbitrary message with the current account * @param message - The message to sign diff --git a/src/types.ts b/src/types.ts index c18d543..69a63fc 100644 --- a/src/types.ts +++ b/src/types.ts @@ -83,10 +83,27 @@ export interface SendTransactionRequest { to: Address; /** Amount to send in nicks (legacy number + canonical string/bigint accepted) */ amount: Nicks; - /** Transaction fee in nicks (legacy number + canonical string/bigint accepted) */ + /** + * Transaction fee in nicks (legacy number + canonical string/bigint accepted). + * Optional: when omitted, the wallet estimates the fee, shows it in the approval + * popup, and auto-calculates the exact fee at build time. The send response + * reports the actual fee used. + */ fee?: Nicks; } +export interface EstimateTransactionFeeRequest { + /** Recipient address (base58-encoded public key hash / PKH) */ + to: Address; + /** Amount to send in nicks (legacy number + canonical string/bigint accepted) */ + amount: Nicks; +} + +export interface EstimateTransactionFeeResponse { + /** Estimated fee in nicks (canonical string) */ + fee: Nicks; +} + export interface SignTxRequest { tx: NockchainTx; /**