diff --git a/.changeset/silly-worms-hear.md b/.changeset/silly-worms-hear.md new file mode 100644 index 0000000..a66aadf --- /dev/null +++ b/.changeset/silly-worms-hear.md @@ -0,0 +1,7 @@ +--- +"@burnt-labs/abstraxion-core": minor +"@burnt-labs/abstraxion": minor +"demo-app": minor +--- + +simulation fix and granter override diff --git a/apps/demo-app/src/app/layout.tsx b/apps/demo-app/src/app/layout.tsx index d98c720..0f2ae0b 100644 --- a/apps/demo-app/src/app/layout.tsx +++ b/apps/demo-app/src/app/layout.tsx @@ -32,8 +32,8 @@ const legacyConfig = { }; const treasuryConfig = { - treasury: "xion1h82c0efsxxq4pgua754u6xepfu6avglup20fl834gc2ah0ptgn5s2zffe9", // Example XION treasury contract with /cosmwasm.wasm.v1.MsgExecuteContract grant - // gasPrice: "0.001uxion", // If you feel the need to change the gasPrice when connecting to signer, set this value. Please stick to the string format seen in example + treasury: "xion1nn55ch09p4a4z30am967n5n8r75m2ag3s3sujutxfmchhsxqtg3qghdg7h", // Example XION treasury instance for executing seat contract + gasPrice: "0.001uxion", // If you feel the need to change the gasPrice when connecting to signer, set this value. Please stick to the string format seen in example // Optional params to activate mainnet config // rpcUrl: "https://rpc.xion-mainnet-1.burnt.com:443", // restUrl: "https://api.xion-mainnet-1.burnt.com:443", diff --git a/packages/abstraxion-core/src/AbstraxionAuth.ts b/packages/abstraxion-core/src/AbstraxionAuth.ts index c4c95b1..9eac87e 100644 --- a/packages/abstraxion-core/src/AbstraxionAuth.ts +++ b/packages/abstraxion-core/src/AbstraxionAuth.ts @@ -208,6 +208,7 @@ export class AbstraxionAuth { gasPrice: GasPrice.fromString("0uxion"), granterAddress, granteeAddress, + treasuryAddress: this.treasury, }, ); diff --git a/packages/abstraxion-core/src/GranteeSignerClient.ts b/packages/abstraxion-core/src/GranteeSignerClient.ts index ce726d2..dd3b209 100644 --- a/packages/abstraxion-core/src/GranteeSignerClient.ts +++ b/packages/abstraxion-core/src/GranteeSignerClient.ts @@ -8,8 +8,14 @@ import { EncodeObject, OfflineSigner, } from "@cosmjs/proto-signing"; -import type { Account, SignerData, StdFee } from "@cosmjs/stargate"; -import type { TxRaw } from "cosmjs-types/cosmos/tx/v1beta1/tx"; +import { + calculateFee, + GasPrice, + type Account, + type SignerData, + type StdFee, +} from "@cosmjs/stargate"; +import { TxRaw } from "cosmjs-types/cosmos/tx/v1beta1/tx"; import { MsgExec } from "cosmjs-types/cosmos/authz/v1beta1/tx"; import { HttpEndpoint, @@ -18,15 +24,19 @@ import { } from "@cosmjs/tendermint-rpc"; import { customAccountFromAny } from "@burnt-labs/signers"; -interface GranteeSignerOptions { +export interface GranteeSignerOptions { readonly granterAddress: string; readonly granteeAddress: string; + readonly treasuryAddress?: string; } export class GranteeSignerClient extends SigningCosmWasmClient { protected readonly granterAddress: string; private readonly _granteeAddress: string; private readonly _signer: OfflineSigner; + private readonly _gasPrice?: GasPrice; + private readonly _treasury?: string; + private readonly _defaultGasMultiplier = 1.4; // cosmjs 0.32.4 default public get granteeAddress(): string { return this._granteeAddress; @@ -65,10 +75,12 @@ export class GranteeSignerClient extends SigningCosmWasmClient { { granterAddress, granteeAddress, + gasPrice, + treasuryAddress, ...options }: SigningCosmWasmClientOptions & GranteeSignerOptions, ) { - super(cometClient, signer, options); + super(cometClient, signer, { ...options, gasPrice }); if (granterAddress === undefined) { throw new Error("granterAddress is required"); } @@ -78,6 +90,8 @@ export class GranteeSignerClient extends SigningCosmWasmClient { throw new Error("granteeAddress is required"); } this._granteeAddress = granteeAddress; + this._gasPrice = gasPrice; + this._treasury = treasuryAddress; this._signer = signer; } @@ -111,7 +125,45 @@ export class GranteeSignerClient extends SigningCosmWasmClient { ]; } - return super.signAndBroadcast(signerAddress, messages, fee, memo); + let usedFee: StdFee; + + const granter = this._treasury ? this._treasury : this.granterAddress; + + if (fee == "auto" || typeof fee === "number") { + if (!this._gasPrice) { + throw new Error( + "Gas price must be set in the client options when auto gas is used", + ); + } + const gasEstimation = await this.simulate(signerAddress, messages, memo); + const multiplier = + typeof fee == "number" ? fee : this._defaultGasMultiplier; + const calculatedFee = calculateFee( + Math.round(gasEstimation * multiplier), + this._gasPrice, + ); + + usedFee = { + ...calculatedFee, + granter, + }; + } else { + usedFee = { ...fee, granter }; + } + + const txRaw = await this.sign( + signerAddress, + messages, + usedFee, + memo, + undefined, + ); + const txBytes = TxRaw.encode(txRaw).finish(); + return this.broadcastTx( + txBytes, + this.broadcastTimeoutMs, + this.broadcastPollIntervalMs, + ); } public async sign( diff --git a/packages/abstraxion/src/hooks/useAbstraxionSigningClient.ts b/packages/abstraxion/src/hooks/useAbstraxionSigningClient.ts index acddd2f..c5408e4 100644 --- a/packages/abstraxion/src/hooks/useAbstraxionSigningClient.ts +++ b/packages/abstraxion/src/hooks/useAbstraxionSigningClient.ts @@ -1,6 +1,5 @@ import { useContext, useEffect, useState } from "react"; -import { testnetChainInfo, xionGasValues } from "@burnt-labs/constants"; -import { GasPrice } from "@cosmjs/stargate"; +import { testnetChainInfo } from "@burnt-labs/constants"; import { GranteeSignerClient, SignArbSecp256k1HdWallet, @@ -22,6 +21,7 @@ export const useAbstraxionSigningClient = (): { rpcUrl, logout, gasPrice, + treasury, } = useContext(AbstraxionContext); const [signArbWallet, setSignArbWallet] = useState< SignArbSecp256k1HdWallet | undefined @@ -59,6 +59,7 @@ export const useAbstraxionSigningClient = (): { gasPrice, granterAddress, granteeAddress, + treasuryAddress: treasury, }, );