diff --git a/Clarinet.toml b/Clarinet.toml index 242ff00..d8b1e58 100644 --- a/Clarinet.toml +++ b/Clarinet.toml @@ -52,15 +52,15 @@ path = 'contracts/aibtcdev-airdrop-2.clar' clarity_version = 2 epoch = 3.0 -# smart wallet and traits +# agent account and traits -[contracts.aibtc-smart-wallet-traits] -path = 'contracts/aibtc-smart-wallet-traits.clar' +[contracts.aibtc-user-agent-account-traits] +path = 'contracts/aibtc-user-agent-account-traits.clar' clarity_version = 3 epoch = 3.1 -[contracts.aibtc-user-agent-smart-wallet] -path = 'contracts/aibtc-user-agent-smart-wallet.clar' +[contracts.aibtc-user-agent-account] +path = 'contracts/aibtc-user-agent-account.clar' clarity_version = 3 epoch = 3.1 diff --git a/contracts/aibtc-smart-wallet-traits.clar b/contracts/aibtc-smart-wallet-traits.clar deleted file mode 100644 index 6db1c25..0000000 --- a/contracts/aibtc-smart-wallet-traits.clar +++ /dev/null @@ -1,103 +0,0 @@ -;; title: aibtc-smart-wallet-traits -;; version: 1.0.0 -;; summary: A collection of traits for user agent smart wallets. - -;; IMPORTS -(use-trait sip010-trait 'SP3FBR2AGK5H9QBDH3EEN6DF8EK8JY7RX8QJ5SVTE.sip-010-trait-ft-standard.sip-010-trait) -(use-trait dao-action-trait .aibtc-dao-traits-v3.action) -(use-trait dao-proposal-trait .aibtc-dao-traits-v3.proposal) -(use-trait dao-action-proposals-trait .aibtc-dao-traits-v3.action-proposals) -(use-trait dao-core-proposals-trait .aibtc-dao-traits-v3.core-proposals) -(use-trait dao-faktory-dex .aibtc-dao-traits-v3.faktory-dex) -(use-trait faktory-token .faktory-trait-v1.sip-010-trait) - -;; SMART WALLET TRAITS - -(define-trait aibtc-smart-wallet ( - ;; deposit STX to the smart wallet - ;; @param amount amount of microSTX to deposit - ;; @returns (response bool uint) - (deposit-stx (uint) (response bool uint)) - ;; deposit FT to the smart wallet - ;; @param ft the fungible token contract - ;; @param amount amount of tokens to deposit - ;; @returns (response bool uint) - (deposit-ft ( uint) (response bool uint)) - ;; withdraw STX from the smart wallet (user only) - ;; @param amount amount of microSTX to withdraw - ;; @returns (response bool uint) - (withdraw-stx (uint) (response bool uint)) - ;; withdraw FT from the smart wallet (user only) - ;; @param ft the fungible token contract - ;; @param amount amount of tokens to withdraw - ;; @returns (response bool uint) - (withdraw-ft ( uint) (response bool uint)) - ;; approve an asset for deposit/withdrawal (user only) - ;; @param asset the asset contract principal - ;; @returns (response bool uint) - (approve-asset (principal) (response bool uint)) - ;; revoke approval for an asset (user only) - ;; @param asset the asset contract principal - ;; @returns (response bool uint) - (revoke-asset (principal) (response bool uint)) -)) - -(define-trait aibtc-proposals-v2 ( - ;; propose an action to the DAO (user or agent) - ;; @param action-proposals the action proposals contract - ;; @param action the action contract - ;; @param parameters encoded action parameters - ;; @returns (response bool uint) - (proxy-propose-action ( (buff 2048) (optional (string-ascii 1024))) (response bool uint)) - ;; create a core proposal to the DAO (user or agent) - ;; @param core-proposals the core proposals contract - ;; @param proposal the proposal contract - ;; @returns (response bool uint) - (proxy-create-proposal ( (optional (string-ascii 1024))) (response bool uint)) - ;; vote on an action proposal (user or agent) - ;; @param action-proposals the action proposals contract - ;; @param proposalId the proposal ID - ;; @param vote true for yes, false for no - ;; @returns (response bool uint) - (vote-on-action-proposal ( uint bool) (response bool uint)) - ;; vote on a core proposal (user or agent) - ;; @param core-proposals the core proposals contract - ;; @param proposal the proposal contract - ;; @param vote true for yes, false for no - ;; @returns (response bool uint) - (vote-on-core-proposal ( bool) (response bool uint)) - ;; conclude an action proposal (user or agent) - ;; @param action-proposals the action proposals contract - ;; @param proposalId the proposal ID - ;; @param action the action contract - ;; @returns (response bool uint) - (conclude-action-proposal ( uint ) (response bool uint)) - ;; conclude a core proposal (user or agent) - ;; @param core-proposals the core proposals contract - ;; @param proposal the proposal contract - ;; @returns (response bool uint) - (conclude-core-proposal ( ) (response bool uint)) -)) - -(define-trait faktory-buy-sell ( - ;; buy an asset from a faktory dex - ;; @param faktory-dex the faktory dex contract - ;; @param asset the asset contract principal - ;; @param amount amount of tokens to buy - ;; @returns (response bool uint) - (buy-asset ( uint) (response bool uint)) - ;; sell an asset to a faktory dex - ;; @param faktory-dex the faktory dex contract - ;; @param asset the asset contract principal - ;; @param amount amount of tokens to sell - ;; @returns (response bool uint) - (sell-asset ( uint) (response bool uint)) - ;; approve a dex for trading an asset - ;; @param faktory-dex the faktory dex contract - ;; @returns (response bool uint) - (approve-dex () (response bool uint)) - ;; revoke approval for a dex - ;; @param faktory-dex the faktory dex contract - ;; @returns (response bool uint) - (revoke-dex () (response bool uint)) -)) diff --git a/contracts/aibtc-smart-wallet-traits-v2.clar b/contracts/aibtc-user-agent-account-traits.clar similarity index 78% rename from contracts/aibtc-smart-wallet-traits-v2.clar rename to contracts/aibtc-user-agent-account-traits.clar index ca49cac..1e948ec 100644 --- a/contracts/aibtc-smart-wallet-traits-v2.clar +++ b/contracts/aibtc-user-agent-account-traits.clar @@ -1,6 +1,6 @@ -;; title: aibtc-smart-wallet-traits -;; version: 2.0.0 -;; summary: A collection of traits for user agent smart wallets. +;; title: aibtc-user-agent-account-traits +;; version: 1.0.0 +;; summary: A collection of traits for user agent accounts. ;; IMPORTS (use-trait sip010-trait 'SP3FBR2AGK5H9QBDH3EEN6DF8EK8JY7RX8QJ5SVTE.sip-010-trait-ft-standard.sip-010-trait) @@ -11,32 +11,32 @@ (use-trait dao-faktory-dex .aibtc-dao-traits-v3.faktory-dex) (use-trait faktory-token .faktory-trait-v1.sip-010-trait) -;; SMART WALLET TRAITS +;; ACCOUNT TRAITS -(define-trait aibtc-smart-wallet ( - ;; deposit STX to the smart wallet +(define-trait aibtc-account ( + ;; deposit STX to the agent account ;; @param amount amount of microSTX to deposit ;; @returns (response bool uint) (deposit-stx (uint) (response bool uint)) - ;; deposit FT to the smart wallet + ;; deposit FT to the agent account ;; @param ft the fungible token contract ;; @param amount amount of tokens to deposit ;; @returns (response bool uint) (deposit-ft ( uint) (response bool uint)) - ;; withdraw STX from the smart wallet (user only) + ;; withdraw STX from the agent account (owner only) ;; @param amount amount of microSTX to withdraw ;; @returns (response bool uint) (withdraw-stx (uint) (response bool uint)) - ;; withdraw FT from the smart wallet (user only) + ;; withdraw FT from the agent account (owner only) ;; @param ft the fungible token contract ;; @param amount amount of tokens to withdraw ;; @returns (response bool uint) (withdraw-ft ( uint) (response bool uint)) - ;; approve an asset for deposit/withdrawal (user only) + ;; approve an asset for deposit/withdrawal (owner only) ;; @param asset the asset contract principal ;; @returns (response bool uint) (approve-asset (principal) (response bool uint)) - ;; revoke approval for an asset (user only) + ;; revoke approval for an asset (owner only) ;; @param asset the asset contract principal ;; @returns (response bool uint) (revoke-asset (principal) (response bool uint)) @@ -48,12 +48,12 @@ ;; @param action the action contract ;; @param parameters encoded action parameters ;; @returns (response bool uint) - (proxy-propose-action ( (buff 2048) (optional (string-ascii 1024))) (response bool uint)) + (acct-propose-action ( (buff 2048) (optional (string-ascii 1024))) (response bool uint)) ;; create a core proposal to the DAO (user or agent) ;; @param core-proposals the core proposals contract ;; @param proposal the proposal contract ;; @returns (response bool uint) - (proxy-create-proposal ( (optional (string-ascii 1024))) (response bool uint)) + (acct-create-proposal ( (optional (string-ascii 1024))) (response bool uint)) ;; vote on an action proposal (user or agent) ;; @param action-proposals the action proposals contract ;; @param proposalId the proposal ID @@ -79,25 +79,28 @@ (conclude-core-proposal ( ) (response bool uint)) )) +(define-trait faktory-dex-approval ( + ;; approve a dex for trading an asset + ;; @param faktory-dex the faktory dex contract + ;; @returns (response bool uint) + (acct-approve-dex () (response bool uint)) + ;; revoke approval for a dex + ;; @param faktory-dex the faktory dex contract + ;; @returns (response bool uint) + (acct-revoke-dex () (response bool uint)) +)) + (define-trait faktory-buy-sell ( ;; buy an asset from a faktory dex ;; @param faktory-dex the faktory dex contract ;; @param asset the asset contract principal ;; @param amount amount of tokens to buy ;; @returns (response bool uint) - (buy-asset ( uint) (response bool uint)) + (acct-buy-asset ( uint) (response bool uint)) ;; sell an asset to a faktory dex ;; @param faktory-dex the faktory dex contract ;; @param asset the asset contract principal ;; @param amount amount of tokens to sell ;; @returns (response bool uint) - (sell-asset ( uint) (response bool uint)) - ;; approve a dex for trading an asset - ;; @param faktory-dex the faktory dex contract - ;; @returns (response bool uint) - (approve-dex () (response bool uint)) - ;; revoke approval for a dex - ;; @param faktory-dex the faktory dex contract - ;; @returns (response bool uint) - (revoke-dex () (response bool uint)) + (acct-sell-asset ( uint) (response bool uint)) )) diff --git a/contracts/aibtc-user-agent-smart-wallet.clar b/contracts/aibtc-user-agent-account.clar similarity index 75% rename from contracts/aibtc-user-agent-smart-wallet.clar rename to contracts/aibtc-user-agent-account.clar index 4cf9d94..1de7ef9 100644 --- a/contracts/aibtc-user-agent-smart-wallet.clar +++ b/contracts/aibtc-user-agent-account.clar @@ -1,11 +1,12 @@ -;; title: aibtc-user-agent-smart-wallet +;; title: aibtc-user-agent-account ;; version: 1.0.0 -;; summary: A smart wallet contract between a user and an agent for managing assets and DAO interactions +;; summary: A special account contract between a user and an agent for managing assets and DAO interactions. Only the user can withdraw funds. ;; traits -(impl-trait .aibtc-smart-wallet-traits.aibtc-smart-wallet) -(impl-trait .aibtc-smart-wallet-traits.aibtc-proposals-v2) -(impl-trait .aibtc-smart-wallet-traits.faktory-buy-sell) +(impl-trait .aibtc-user-agent-account-traits.aibtc-account) +(impl-trait .aibtc-user-agent-account-traits.aibtc-proposals-v3) +(impl-trait .aibtc-user-agent-account-traits.faktory-dex-approval) +(impl-trait .aibtc-user-agent-account-traits.faktory-buy-sell) (use-trait ft-trait 'SP3FBR2AGK5H9QBDH3EEN6DF8EK8JY7RX8QJ5SVTE.sip-010-trait-ft-standard.sip-010-trait) (use-trait action-trait .aibtc-dao-traits-v3.action) (use-trait proposal-trait .aibtc-dao-traits-v3.proposal) @@ -18,15 +19,22 @@ (define-constant DEPLOYED_BURN_BLOCK burn-block-height) (define-constant DEPLOYED_STACKS_BLOCK stacks-block-height) (define-constant SELF (as-contract tx-sender)) -(define-constant USER 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM) ;; user (smart wallet owner) -(define-constant AGENT 'ST2CY5V39NHDPWSXMW9QDT3HC3GD6Q6XX4CFRK9AG) ;; agent (proposal voter) -;; Pre-approved contracts +;; owner and agent addresses +;; /g/ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM/account_owner +(define-constant ACCOUNT_OWNER 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM) ;; owner (user/creator of account, full access) +;; /g/ST2CY5V39NHDPWSXMW9QDT3HC3GD6Q6XX4CFRK9AG/account_agent +(define-constant ACCOUNT_AGENT 'ST2CY5V39NHDPWSXMW9QDT3HC3GD6Q6XX4CFRK9AG) ;; agent (can only take approved actions) + +;; pre-approved contracts +;; /g/STV9K21TBFAK4KNRJXF5DFP8N7W46G4V9RJ5XDY2.sbtc-token/sbtc_contract (define-constant SBTC_TOKEN 'STV9K21TBFAK4KNRJXF5DFP8N7W46G4V9RJ5XDY2.sbtc-token) ;; sBTC token +;; /g/.aibtc-token/dao_token_contract (define-constant DAO_TOKEN .aibtc-token) ;; DAO token +;; /g/.aibtc-token-dex/dao_token_dex_contract (define-constant DAO_TOKEN_DEX .aibtc-token-dex) ;; DAO token DEX -;; Error codes +;; error codes (define-constant ERR_UNAUTHORIZED (err u9000)) (define-constant ERR_UNKNOWN_ASSET (err u9001)) (define-constant ERR_OPERATION_FAILED (err u9002)) @@ -37,7 +45,6 @@ (define-map ApprovedDexes principal bool) ;; data vars - (define-data-var agentCanBuySell bool false) ;; public functions @@ -78,23 +85,23 @@ (define-public (withdraw-stx (amount uint)) (begin - (asserts! (is-user) ERR_UNAUTHORIZED) + (asserts! (is-owner) ERR_UNAUTHORIZED) (print { notification: "withdraw-stx", payload: { amount: amount, sender: SELF, caller: contract-caller, - recipient: USER + recipient: ACCOUNT_OWNER } }) - (as-contract (stx-transfer? amount SELF USER)) + (as-contract (stx-transfer? amount SELF ACCOUNT_OWNER)) ) ) (define-public (withdraw-ft (ft ) (amount uint)) (begin - (asserts! (is-user) ERR_UNAUTHORIZED) + (asserts! (is-owner) ERR_UNAUTHORIZED) (asserts! (is-approved-asset (contract-of ft)) ERR_UNKNOWN_ASSET) (print { notification: "withdraw-ft", @@ -103,16 +110,16 @@ assetContract: (contract-of ft), sender: SELF, caller: contract-caller, - recipient: USER + recipient: ACCOUNT_OWNER } }) - (as-contract (contract-call? ft transfer amount SELF USER none)) + (as-contract (contract-call? ft transfer amount SELF ACCOUNT_OWNER none)) ) ) (define-public (approve-asset (asset principal)) (begin - (asserts! (is-user) ERR_UNAUTHORIZED) + (asserts! (is-owner) ERR_UNAUTHORIZED) (print { notification: "approve-asset", payload: { @@ -128,7 +135,7 @@ (define-public (revoke-asset (asset principal)) (begin - (asserts! (is-user) ERR_UNAUTHORIZED) + (asserts! (is-owner) ERR_UNAUTHORIZED) (print { notification: "revoke-asset", payload: { @@ -144,11 +151,11 @@ ;; DAO Interaction Functions -(define-public (proxy-propose-action (action-proposals ) (action ) (parameters (buff 2048)) (memo (optional (string-ascii 1024)))) +(define-public (acct-propose-action (action-proposals ) (action ) (parameters (buff 2048)) (memo (optional (string-ascii 1024)))) (begin (asserts! (is-authorized) ERR_UNAUTHORIZED) (print { - notification: "proxy-propose-action", + notification: "acct-propose-action", payload: { proposalContract: (contract-of action-proposals), action: (contract-of action), @@ -161,11 +168,11 @@ ) ) -(define-public (proxy-create-proposal (core-proposals ) (proposal ) (memo (optional (string-ascii 1024)))) +(define-public (acct-create-proposal (core-proposals ) (proposal ) (memo (optional (string-ascii 1024)))) (begin (asserts! (is-authorized) ERR_UNAUTHORIZED) (print { - notification: "proxy-create-proposal", + notification: "acct-create-proposal", payload: { proposalContract: (contract-of core-proposals), proposal: (contract-of proposal), @@ -246,12 +253,12 @@ ;; Faktory DEX Trading Functions -(define-public (buy-asset (faktory-dex ) (asset ) (amount uint)) +(define-public (acct-buy-asset (faktory-dex ) (asset ) (amount uint)) (begin (asserts! (buy-sell-allowed) ERR_BUY_SELL_NOT_ALLOWED) (asserts! (is-approved-dex (contract-of faktory-dex)) ERR_UNKNOWN_ASSET) (print { - notification: "buy-asset", + notification: "acct-buy-asset", payload: { dexContract: (contract-of faktory-dex), asset: (contract-of asset), @@ -264,12 +271,12 @@ ) ) -(define-public (sell-asset (faktory-dex ) (asset ) (amount uint)) +(define-public (acct-sell-asset (faktory-dex ) (asset ) (amount uint)) (begin (asserts! (buy-sell-allowed) ERR_BUY_SELL_NOT_ALLOWED) (asserts! (is-approved-dex (contract-of faktory-dex)) ERR_UNKNOWN_ASSET) (print { - notification: "sell-asset", + notification: "acct-sell-asset", payload: { dexContract: (contract-of faktory-dex), asset: (contract-of asset), @@ -282,11 +289,11 @@ ) ) -(define-public (approve-dex (faktory-dex )) +(define-public (acct-approve-dex (faktory-dex )) (begin - (asserts! (is-user) ERR_UNAUTHORIZED) + (asserts! (is-owner) ERR_UNAUTHORIZED) (print { - notification: "approve-dex", + notification: "acct-approve-dex", payload: { dexContract: (contract-of faktory-dex), approved: true, @@ -298,11 +305,11 @@ ) ) -(define-public (revoke-dex (faktory-dex )) +(define-public (acct-revoke-dex (faktory-dex )) (begin - (asserts! (is-user) ERR_UNAUTHORIZED) + (asserts! (is-owner) ERR_UNAUTHORIZED) (print { - notification: "revoke-dex", + notification: "acct-revoke-dex", payload: { dexContract: (contract-of faktory-dex), approved: false, @@ -316,7 +323,7 @@ (define-public (set-agent-can-buy-sell (canBuySell bool)) (begin - (asserts! (is-user) ERR_UNAUTHORIZED) + (asserts! (is-owner) ERR_UNAUTHORIZED) (print { notification: "set-agent-can-buy-sell", payload: { @@ -345,9 +352,9 @@ (define-read-only (get-configuration) { - agent: AGENT, - user: USER, - smartWallet: SELF, + account: SELF, + agent: ACCOUNT_AGENT, + owner: ACCOUNT_OWNER, daoToken: DAO_TOKEN, daoTokenDex: DAO_TOKEN_DEX, sbtcToken: SBTC_TOKEN, @@ -357,19 +364,19 @@ ;; private functions (define-private (is-authorized) - (or (is-eq contract-caller USER) (is-eq contract-caller AGENT)) + (or (is-eq contract-caller ACCOUNT_OWNER) (is-eq contract-caller ACCOUNT_AGENT)) ) -(define-private (is-user) - (is-eq contract-caller USER) +(define-private (is-owner) + (is-eq contract-caller ACCOUNT_OWNER) ) (define-private (is-agent) - (is-eq contract-caller AGENT) + (is-eq contract-caller ACCOUNT_AGENT) ) (define-private (buy-sell-allowed) - (or (is-user) (and (is-agent) (var-get agentCanBuySell))) + (or (is-owner) (and (is-agent) (var-get agentCanBuySell))) ) ;; initialize approved contracts @@ -379,6 +386,6 @@ ;; print creation event (print { - notification: "smart-wallet-created", + notification: "user-agent-account-created", payload: (get-configuration) }) diff --git a/tests/aibtc-user-agent-smart-wallet.test.ts b/tests/aibtc-user-agent-account.test.ts similarity index 85% rename from tests/aibtc-user-agent-smart-wallet.test.ts rename to tests/aibtc-user-agent-account.test.ts index c7a1b0d..00bd751 100644 --- a/tests/aibtc-user-agent-smart-wallet.test.ts +++ b/tests/aibtc-user-agent-account.test.ts @@ -1,6 +1,13 @@ -import { Cl, cvToValue } from "@stacks/transactions"; +import { + Cl, + ClarityType, + ClarityValue, + cvToValue, + isClarityType, + TupleCV, +} from "@stacks/transactions"; import { describe, expect, it } from "vitest"; -import { UserAgentSmartWalletErrCode } from "./error-codes"; +import { UserAgentAccountErrCode } from "./error-codes"; import { constructDao, convertSIP019PrintEvent, @@ -20,7 +27,7 @@ const address2 = accounts.get("wallet_2")!; const address3 = accounts.get("wallet_3")!; // Contract references -const contractName = "aibtc-user-agent-smart-wallet"; +const contractName = "aibtc-user-agent-account"; const contractAddress = `${deployer}.${contractName}`; const daoTokenAddress = `${deployer}.aibtc-token`; const tokenDexContractAddress = `${deployer}.aibtc-token-dex`; @@ -36,9 +43,9 @@ const actionProposalVotingConfig = VOTING_CONFIG["aibtc-action-proposals-v2"]; const coreProposalVotingConfig = VOTING_CONFIG["aibtc-core-proposals-v2"]; // Error codes -const ErrCode = UserAgentSmartWalletErrCode; +const ErrCode = UserAgentAccountErrCode; -function setupSmartWallet(sender: string, satsAmount: number = 1000000) { +function setupAccount(sender: string, satsAmount: number = 1000000) { // construct the dao so we can call extensions const constructReceipt = constructDao( sender, @@ -90,7 +97,7 @@ describe(`public functions: ${contractName}`, () => { //////////////////////////////////////// // deposit-stx() tests //////////////////////////////////////// - it("deposit-stx() succeeds and deposits STX to the smart wallet", () => { + it("deposit-stx() succeeds and deposits STX to the account", () => { // arrange const amount = 1000000; // 1 STX const initialBalanceResponse = simnet.callReadOnlyFn( @@ -169,7 +176,7 @@ describe(`public functions: ${contractName}`, () => { // assert expect(receipt.result).toBeErr(Cl.uint(ErrCode.ERR_UNKNOWN_ASSET)); }); - it("deposit-ft() succeeds and transfers sBTC to the smart wallet", () => { + it("deposit-ft() succeeds and transfers sBTC to the account", () => { // arrange const sbtcAmount = 100000000; // get sBTC from the faucet @@ -190,7 +197,7 @@ describe(`public functions: ${contractName}`, () => { // assert expect(receipt.result).toBeOk(Cl.bool(true)); }); - it("deposit-ft() succeeds and transfers DAO tokens to the smart wallet", () => { + it("deposit-ft() succeeds and transfers DAO tokens to the account", () => { // arrange const amount = 1000000; // get sBTC from the faucet @@ -584,13 +591,13 @@ describe(`public functions: ${contractName}`, () => { //////////////////////////////////////// const memoContext = "Can pass up to 1024 characters for additional context."; - it("proxy-propose-action() fails if caller is not authorized (user or agent)", () => { + it("acct-propose-action() fails if caller is not authorized (user or agent)", () => { // arrange const message = Cl.stringAscii("hello world"); // act const receipt = simnet.callPublicFn( contractAddress, - "proxy-propose-action", + "acct-propose-action", [ Cl.principal(actionProposalsV2ContractAddress), Cl.principal(sendMessageActionContractAddress), @@ -602,15 +609,15 @@ describe(`public functions: ${contractName}`, () => { // assert expect(receipt.result).toBeErr(Cl.uint(ErrCode.ERR_UNAUTHORIZED)); }); - it("proxy-propose-action() succeeds and creates a new action proposal", () => { + it("acct-propose-action() succeeds and creates a new action proposal", () => { // arrange const message = Cl.stringAscii("hello world"); - // construct dao / setup smart wallet with dao tokens - setupSmartWallet(deployer); + // construct dao / setup account with dao tokens + setupAccount(deployer); // act const receipt = simnet.callPublicFn( contractAddress, - "proxy-propose-action", + "acct-propose-action", [ Cl.principal(actionProposalsV2ContractAddress), Cl.principal(sendMessageActionContractAddress), @@ -622,11 +629,11 @@ describe(`public functions: ${contractName}`, () => { // assert expect(receipt.result).toBeOk(Cl.bool(true)); }); - it("proxy-propose-action() emits the correct notification event", () => { + it("acct-propose-action() emits the correct notification event", () => { // arrange const message = Cl.stringAscii("hello world"); const expectedEvent = { - notification: "proxy-propose-action", + notification: "acct-propose-action", payload: { proposalContract: actionProposalsV2ContractAddress, action: sendMessageActionContractAddress, @@ -635,12 +642,12 @@ describe(`public functions: ${contractName}`, () => { caller: deployer, }, }; - // construct dao / setup smart wallet with dao tokens - setupSmartWallet(deployer); + // construct dao / setup account with dao tokens + setupAccount(deployer); // act const receipt = simnet.callPublicFn( contractAddress, - "proxy-propose-action", + "acct-propose-action", [ Cl.principal(actionProposalsV2ContractAddress), Cl.principal(sendMessageActionContractAddress), @@ -659,11 +666,11 @@ describe(`public functions: ${contractName}`, () => { //////////////////////////////////////// // proxy-create-proposal() tests //////////////////////////////////////// - it("proxy-create-proposal() fails if caller is not authorized (user or agent)", () => { + it("acct-create-proposal() fails if caller is not authorized (user or agent)", () => { // act const receipt = simnet.callPublicFn( contractAddress, - "proxy-create-proposal", + "acct-create-proposal", [ Cl.principal(coreProposalsV2ContractAddress), Cl.principal(baseEnableExtensionContractAddress), @@ -674,16 +681,16 @@ describe(`public functions: ${contractName}`, () => { // assert expect(receipt.result).toBeErr(Cl.uint(ErrCode.ERR_UNAUTHORIZED)); }); - it("proxy-create-proposal() succeeds and creates a new core proposal", () => { + it("acct-create-proposal() succeeds and creates a new core proposal", () => { // arrange - // construct dao / setup smart wallet with dao tokens - setupSmartWallet(deployer); + // construct dao / setup account with dao tokens + setupAccount(deployer); // progress the chain past the first voting period simnet.mineEmptyBlocks(coreProposalVotingConfig.votingPeriod); // act const receipt = simnet.callPublicFn( contractAddress, - "proxy-create-proposal", + "acct-create-proposal", [ Cl.principal(coreProposalsV2ContractAddress), Cl.principal(baseEnableExtensionContractAddress), @@ -694,15 +701,15 @@ describe(`public functions: ${contractName}`, () => { // assert expect(receipt.result).toBeOk(Cl.bool(true)); }); - it("proxy-create-proposal() emits the correct notification event", () => { + it("acct-create-proposal() emits the correct notification event", () => { // arrange - // construct dao / setup smart wallet with dao tokens - setupSmartWallet(deployer); + // construct dao / setup account with dao tokens + setupAccount(deployer); // progress the chain past the first voting period simnet.mineEmptyBlocks(coreProposalVotingConfig.votingPeriod); // format expected event like print event const expectedEvent = { - notification: "proxy-create-proposal", + notification: "acct-create-proposal", payload: { proposalContract: coreProposalsV2ContractAddress, proposal: baseEnableExtensionContractAddress, @@ -713,7 +720,7 @@ describe(`public functions: ${contractName}`, () => { // act const receipt = simnet.callPublicFn( contractAddress, - "proxy-create-proposal", + "acct-create-proposal", [ Cl.principal(coreProposalsV2ContractAddress), Cl.principal(baseEnableExtensionContractAddress), @@ -754,12 +761,12 @@ describe(`public functions: ${contractName}`, () => { const message = Cl.stringAscii("hello world"); const proposalId = 1; const vote = true; - // construct dao / setup smart wallet with dao tokens - setupSmartWallet(deployer); + // construct dao / setup account with dao tokens + setupAccount(deployer); // create a new action proposal const proposeReceipt = simnet.callPublicFn( contractAddress, - "proxy-propose-action", + "acct-propose-action", [ Cl.principal(actionProposalsV2ContractAddress), Cl.principal(sendMessageActionContractAddress), @@ -790,12 +797,12 @@ describe(`public functions: ${contractName}`, () => { const message = Cl.stringAscii("hello world"); const proposalId = 1; const vote = true; - // construct dao / setup smart wallet with dao tokens - setupSmartWallet(deployer); + // construct dao / setup account with dao tokens + setupAccount(deployer); // create a new action proposal const proposeReceipt = simnet.callPublicFn( contractAddress, - "proxy-propose-action", + "acct-propose-action", [ Cl.principal(actionProposalsV2ContractAddress), Cl.principal(sendMessageActionContractAddress), @@ -859,14 +866,14 @@ describe(`public functions: ${contractName}`, () => { it("vote-on-core-proposal() succeeds and votes on a core proposal", () => { // arrange const vote = true; - // construct dao / setup smart wallet with dao tokens - setupSmartWallet(deployer); + // construct dao / setup account with dao tokens + setupAccount(deployer); // progress the chain past the first voting period simnet.mineEmptyBlocks(coreProposalVotingConfig.votingPeriod); // create a new core proposal const createReceipt = simnet.callPublicFn( contractAddress, - "proxy-create-proposal", + "acct-create-proposal", [ Cl.principal(coreProposalsV2ContractAddress), Cl.principal(baseEnableExtensionContractAddress), @@ -894,14 +901,14 @@ describe(`public functions: ${contractName}`, () => { it("vote-on-core-proposal() emits the correct notification event", () => { // arrange const vote = true; - // construct dao / setup smart wallet with dao tokens - setupSmartWallet(deployer); + // construct dao / setup account with dao tokens + setupAccount(deployer); // progress the chain past the first voting period simnet.mineEmptyBlocks(coreProposalVotingConfig.votingPeriod); // create a new core proposal const createReceipt = simnet.callPublicFn( contractAddress, - "proxy-create-proposal", + "acct-create-proposal", [ Cl.principal(coreProposalsV2ContractAddress), Cl.principal(baseEnableExtensionContractAddress), @@ -965,8 +972,8 @@ describe(`public functions: ${contractName}`, () => { // arrange const message = Cl.stringAscii("hello world"); const proposalId = 1; - // construct dao / setup smart wallet with dao tokens - setupSmartWallet(deployer); + // construct dao / setup account with dao tokens + setupAccount(deployer); fundVoters(daoTokenAddress, tokenDexContractAddress, [ deployer, address1, @@ -975,7 +982,7 @@ describe(`public functions: ${contractName}`, () => { // create a new action proposal const proposeReceipt = simnet.callPublicFn( contractAddress, - "proxy-propose-action", + "acct-propose-action", [ Cl.principal(actionProposalsV2ContractAddress), Cl.principal(sendMessageActionContractAddress), @@ -1002,7 +1009,7 @@ describe(`public functions: ${contractName}`, () => { [Cl.uint(proposalId), Cl.bool(true)], address1 ), - // cast vote through our user/agent smart wallet + // cast vote through our user/agent account simnet.callPublicFn( contractAddress, "vote-on-action-proposal", @@ -1041,15 +1048,15 @@ describe(`public functions: ${contractName}`, () => { const expectedEvent = { notification: "conclude-action-proposal", payload: { - action: sendMessageActionContractAddress, - caller: deployer, proposalContract: actionProposalsV2ContractAddress, proposalId: proposalId.toString(), + action: sendMessageActionContractAddress, sender: deployer, + caller: deployer, }, }; - // construct dao / setup smart wallet with dao tokens - setupSmartWallet(deployer); + // construct dao / setup account with dao tokens + setupAccount(deployer); fundVoters(daoTokenAddress, tokenDexContractAddress, [ deployer, address1, @@ -1058,7 +1065,7 @@ describe(`public functions: ${contractName}`, () => { // create a new action proposal const proposeReceipt = simnet.callPublicFn( contractAddress, - "proxy-propose-action", + "acct-propose-action", [ Cl.principal(actionProposalsV2ContractAddress), Cl.principal(sendMessageActionContractAddress), @@ -1085,7 +1092,7 @@ describe(`public functions: ${contractName}`, () => { [Cl.uint(proposalId), Cl.bool(true)], address1 ), - // cast vote through our user/agent smart wallet + // cast vote through our user/agent account simnet.callPublicFn( contractAddress, "vote-on-action-proposal", @@ -1140,8 +1147,90 @@ describe(`public functions: ${contractName}`, () => { }); it("conclude-core-proposal() succeeds and concludes a core proposal", () => { // arrange - // construct dao / setup smart wallet with dao tokens - setupSmartWallet(deployer); + // construct dao / setup account with dao tokens + setupAccount(deployer); + fundVoters(daoTokenAddress, tokenDexContractAddress, [ + deployer, + address1, + address2, + ]); + // progress the chain past the first voting period + simnet.mineEmptyBlocks(coreProposalVotingConfig.votingPeriod); + // create a new core proposal + const createReceipt = simnet.callPublicFn( + contractAddress, + "acct-create-proposal", + [ + Cl.principal(coreProposalsV2ContractAddress), + Cl.principal(baseEnableExtensionContractAddress), + Cl.some(Cl.stringAscii(memoContext)), + ], + deployer + ); + expect(createReceipt.result).toBeOk(Cl.bool(true)); + // progress the chain past the voting delay + simnet.mineEmptyBlocks(coreProposalVotingConfig.votingDelay); + // vote on the proposal + const voteReceipts = [ + // cast two regular votes to pass proposal + simnet.callPublicFn( + coreProposalsV2ContractAddress, + "vote-on-proposal", + [Cl.principal(baseEnableExtensionContractAddress), Cl.bool(true)], + address2 + ), + simnet.callPublicFn( + coreProposalsV2ContractAddress, + "vote-on-proposal", + [Cl.principal(baseEnableExtensionContractAddress), Cl.bool(true)], + address1 + ), + // cast vote through our user/agent account + simnet.callPublicFn( + contractAddress, + "vote-on-core-proposal", + [ + Cl.principal(coreProposalsV2ContractAddress), + Cl.principal(baseEnableExtensionContractAddress), + Cl.bool(true), + ], + deployer + ), + ]; + for (const voteReceipt of voteReceipts) { + expect(voteReceipt.result).toBeOk(Cl.bool(true)); + } + // progress the chain past the voting period and execution delay + simnet.mineEmptyBlocks(coreProposalVotingConfig.votingPeriod); + simnet.mineEmptyBlocks(coreProposalVotingConfig.votingDelay); + // act + const receipt = simnet.callPublicFn( + contractAddress, + "conclude-core-proposal", + [ + Cl.principal(coreProposalsV2ContractAddress), + Cl.principal(baseEnableExtensionContractAddress), + ], + deployer + ); + // assert + expect(receipt.result).toBeOk(Cl.bool(true)); + }); + + it("conclude-core-proposal() emits the correct notification event", () => { + // arrange + const vote = true; + const expectedEvent = { + notification: "conclude-core-proposal", + payload: { + proposalContract: coreProposalsV2ContractAddress, + proposal: baseEnableExtensionContractAddress, + sender: deployer, + caller: deployer, + }, + }; + // construct dao / setup account with dao tokens + setupAccount(deployer); fundVoters(daoTokenAddress, tokenDexContractAddress, [ deployer, address1, @@ -1152,7 +1241,7 @@ describe(`public functions: ${contractName}`, () => { // create a new core proposal const createReceipt = simnet.callPublicFn( contractAddress, - "proxy-create-proposal", + "acct-create-proposal", [ Cl.principal(coreProposalsV2ContractAddress), Cl.principal(baseEnableExtensionContractAddress), @@ -1178,7 +1267,7 @@ describe(`public functions: ${contractName}`, () => { [Cl.principal(baseEnableExtensionContractAddress), Cl.bool(true)], address1 ), - // cast vote through our user/agent smart wallet + // cast vote through our user/agent account simnet.callPublicFn( contractAddress, "vote-on-core-proposal", @@ -1208,30 +1297,34 @@ describe(`public functions: ${contractName}`, () => { ); // assert expect(receipt.result).toBeOk(Cl.bool(true)); + const event = receipt.events[0]; + expect(event).toBeDefined(); + const printEvent = convertSIP019PrintEvent(receipt.events[0]); + expect(printEvent).toStrictEqual(expectedEvent); }); //////////////////////////////////////// - // approve-dex() tests + // acct-approve-dex() tests //////////////////////////////////////// - it("approve-dex() fails if caller is not the user", () => { + it("acct-approve-dex() fails if caller is not the user", () => { // arrange const dex = `${deployer}.test-dex-1`; // act const receipt = simnet.callPublicFn( contractAddress, - "approve-dex", + "acct-approve-dex", [Cl.principal(dex)], address3 ); // assert expect(receipt.result).toBeErr(Cl.uint(ErrCode.ERR_UNAUTHORIZED)); }); - it("approve-dex() succeeds and sets new approved dex", () => { + it("acct-approve-dex() succeeds and sets new approved dex", () => { // arrange const dex = `${deployer}.test-dex-1`; // act const receipt = simnet.callPublicFn( contractAddress, - "approve-dex", + "acct-approve-dex", [Cl.principal(dex)], deployer ); @@ -1246,11 +1339,11 @@ describe(`public functions: ${contractName}`, () => { ); expect(isApproved.result).toStrictEqual(Cl.bool(true)); }); - it("approve-dex() emits the correct notification event", () => { + it("acct-approve-dex() emits the correct notification event", () => { // arrange const dex = `${deployer}.test-dex-2`; const expectedEvent = { - notification: "approve-dex", + notification: "acct-approve-dex", payload: { dexContract: dex, approved: true, @@ -1261,7 +1354,7 @@ describe(`public functions: ${contractName}`, () => { // act const receipt = simnet.callPublicFn( contractAddress, - "approve-dex", + "acct-approve-dex", [Cl.principal(dex)], deployer ); @@ -1273,28 +1366,28 @@ describe(`public functions: ${contractName}`, () => { expect(printEvent).toStrictEqual(expectedEvent); }); //////////////////////////////////////// - // revoke-dex() tests + // acct-revoke-dex() tests //////////////////////////////////////// - it("revoke-dex() fails if caller is not the user", () => { + it("acct-revoke-dex() fails if caller is not the user", () => { // arrange const dex = `${deployer}.test-dex-1`; // act const receipt = simnet.callPublicFn( contractAddress, - "revoke-dex", + "acct-revoke-dex", [Cl.principal(dex)], address3 ); // assert expect(receipt.result).toBeErr(Cl.uint(ErrCode.ERR_UNAUTHORIZED)); }); - it("revoke-dex() succeeds and removes approved dex", () => { + it("acct-revoke-dex() succeeds and removes approved dex", () => { // arrange const dex = `${deployer}.test-dex-1`; // approve the dex first const approveReceipt = simnet.callPublicFn( contractAddress, - "approve-dex", + "acct-approve-dex", [Cl.principal(dex)], deployer ); @@ -1302,7 +1395,7 @@ describe(`public functions: ${contractName}`, () => { // act const receipt = simnet.callPublicFn( contractAddress, - "revoke-dex", + "acct-revoke-dex", [Cl.principal(dex)], deployer ); @@ -1317,11 +1410,11 @@ describe(`public functions: ${contractName}`, () => { ); expect(isApproved.result).toStrictEqual(Cl.bool(false)); }); - it("revoke-dex() emits the correct notification event", () => { + it("acct-revoke-dex() emits the correct notification event", () => { // arrange const dex = `${deployer}.test-dex-1`; const expectedEvent = { - notification: "revoke-dex", + notification: "acct-revoke-dex", payload: { dexContract: dex, approved: false, @@ -1332,7 +1425,7 @@ describe(`public functions: ${contractName}`, () => { // approve the dex first const approveReceipt = simnet.callPublicFn( contractAddress, - "approve-dex", + "acct-approve-dex", [Cl.principal(dex)], deployer ); @@ -1340,7 +1433,7 @@ describe(`public functions: ${contractName}`, () => { // act const receipt = simnet.callPublicFn( contractAddress, - "revoke-dex", + "acct-revoke-dex", [Cl.principal(dex)], deployer ); @@ -1406,9 +1499,9 @@ describe(`public functions: ${contractName}`, () => { expect(printEvent).toStrictEqual(expectedEvent); }); //////////////////////////////////////// - // buy-asset() tests + // acct-buy-asset() tests //////////////////////////////////////// - it("buy-asset() fails if caller is not authorized", () => { + it("acct-buy-asset() fails if caller is not authorized", () => { // arrange const amount = 10000000000; const dex = tokenDexContractAddress; @@ -1416,14 +1509,14 @@ describe(`public functions: ${contractName}`, () => { // act const receipt = simnet.callPublicFn( contractAddress, - "buy-asset", + "acct-buy-asset", [Cl.principal(dex), Cl.principal(asset), Cl.uint(amount)], address3 ); // assert expect(receipt.result).toBeErr(Cl.uint(ErrCode.ERR_BUY_SELL_NOT_ALLOWED)); }); - it("buy-asset() fails if agent can't buy/sell", () => { + it("acct-buy-asset() fails if agent can't buy/sell", () => { // arrange const amount = 10000000000; const dex = tokenDexContractAddress; @@ -1431,14 +1524,14 @@ describe(`public functions: ${contractName}`, () => { // act const receipt = simnet.callPublicFn( contractAddress, - "buy-asset", + "acct-buy-asset", [Cl.principal(dex), Cl.principal(asset), Cl.uint(amount)], address2 // agent address ); // assert expect(receipt.result).toBeErr(Cl.uint(ErrCode.ERR_BUY_SELL_NOT_ALLOWED)); }); - it("buy-asset() fails if dex is not approved", () => { + it("acct-buy-asset() fails if dex is not approved", () => { // arrange const amount = 10000000000; const dex = `${deployer}.test-dex-1`; @@ -1446,49 +1539,49 @@ describe(`public functions: ${contractName}`, () => { // act const receipt = simnet.callPublicFn( contractAddress, - "buy-asset", + "acct-buy-asset", [Cl.principal(dex), Cl.principal(asset), Cl.uint(amount)], deployer ); // assert expect(receipt.result).toBeErr(Cl.uint(ErrCode.ERR_UNKNOWN_ASSET)); }); - it("buy-asset() succeeds when called by user", () => { + it("acct-buy-asset() succeeds when called by user", () => { // arrange const amount = 10000; const dex = tokenDexContractAddress; const asset = daoTokenAddress; - // construct dao / setup smart wallet with dao tokens - setupSmartWallet(deployer); + // construct dao / setup account with dao tokens + setupAccount(deployer); // get our balances from the assets map const balancesMap = simnet.getAssetsMap(); dbgLog(balancesMap); const aibtcKey = ".aibtc-token.SYMBOL"; const sbtcKey = ".sbtc-token.sbtc-token"; const stxKey = "STX"; - const smartWalletBalances = { + const accountBalances = { sbtc: balancesMap.get(sbtcKey)?.get(contractAddress) ?? 0n, aibtc: balancesMap.get(aibtcKey)?.get(contractAddress) ?? 0n, stx: balancesMap.get(stxKey)?.get(contractAddress) ?? 0n, }; - dbgLog(`smartWalletBalances: ${JSON.stringify(smartWalletBalances)}`); + dbgLog(`accountBalances: ${JSON.stringify(accountBalances)}`); // act const receipt = simnet.callPublicFn( contractAddress, - "buy-asset", + "acct-buy-asset", [Cl.principal(dex), Cl.principal(asset), Cl.uint(amount)], deployer ); // assert expect(receipt.result).toBeOk(Cl.bool(true)); }); - it("buy-asset() succeeds when called by agent with permission", () => { + it("acct-buy-asset() succeeds when called by agent with permission", () => { // arrange const amount = 10000; const dex = tokenDexContractAddress; const asset = daoTokenAddress; - // construct dao / setup smart wallet with dao tokens - setupSmartWallet(deployer); + // construct dao / setup account with dao tokens + setupAccount(deployer); // enable agent to buy/sell const permissionReceipt = simnet.callPublicFn( contractAddress, @@ -1500,20 +1593,20 @@ describe(`public functions: ${contractName}`, () => { // act const receipt = simnet.callPublicFn( contractAddress, - "buy-asset", + "acct-buy-asset", [Cl.principal(dex), Cl.principal(asset), Cl.uint(amount)], address2 // agent address ); // assert expect(receipt.result).toBeOk(Cl.bool(true)); }); - it("buy-asset() emits the correct notification event", () => { + it("acct-buy-asset() emits the correct notification event", () => { // arrange const amount = 10000; const dex = tokenDexContractAddress; const asset = daoTokenAddress; const expectedEvent = { - notification: "buy-asset", + notification: "acct-buy-asset", payload: { dexContract: dex, asset: asset, @@ -1522,12 +1615,12 @@ describe(`public functions: ${contractName}`, () => { caller: deployer, }, }; - // construct dao / setup smart wallet with dao tokens - setupSmartWallet(deployer); + // construct dao / setup account with dao tokens + setupAccount(deployer); // act const receipt = simnet.callPublicFn( contractAddress, - "buy-asset", + "acct-buy-asset", [Cl.principal(dex), Cl.principal(asset), Cl.uint(amount)], deployer ); @@ -1539,9 +1632,9 @@ describe(`public functions: ${contractName}`, () => { expect(printEvent).toStrictEqual(expectedEvent); }); //////////////////////////////////////// - // sell-asset() tests + // acct-sell-asset() tests //////////////////////////////////////// - it("sell-asset() fails if caller is not authorized", () => { + it("acct-sell-asset() fails if caller is not authorized", () => { // arrange const amount = 10000000000; const dex = tokenDexContractAddress; @@ -1549,14 +1642,14 @@ describe(`public functions: ${contractName}`, () => { // act const receipt = simnet.callPublicFn( contractAddress, - "sell-asset", + "acct-sell-asset", [Cl.principal(dex), Cl.principal(asset), Cl.uint(amount)], address3 ); // assert expect(receipt.result).toBeErr(Cl.uint(ErrCode.ERR_BUY_SELL_NOT_ALLOWED)); }); - it("sell-asset() fails if agent can't buy/sell", () => { + it("acct-sell-asset() fails if agent can't buy/sell", () => { // arrange const amount = 10000000000; const dex = tokenDexContractAddress; @@ -1572,14 +1665,14 @@ describe(`public functions: ${contractName}`, () => { // act const receipt = simnet.callPublicFn( contractAddress, - "sell-asset", + "acct-sell-asset", [Cl.principal(dex), Cl.principal(asset), Cl.uint(amount)], address2 // agent address ); // assert expect(receipt.result).toBeErr(Cl.uint(ErrCode.ERR_BUY_SELL_NOT_ALLOWED)); }); - it("sell-asset() fails if dex is not approved", () => { + it("acct-sell-asset() fails if dex is not approved", () => { // arrange const amount = 10000000000; const dex = `${deployer}.test-dex-1`; @@ -1587,14 +1680,14 @@ describe(`public functions: ${contractName}`, () => { // act const receipt = simnet.callPublicFn( contractAddress, - "sell-asset", + "acct-sell-asset", [Cl.principal(dex), Cl.principal(asset), Cl.uint(amount)], deployer ); // assert expect(receipt.result).toBeErr(Cl.uint(ErrCode.ERR_UNKNOWN_ASSET)); }); - it("sell-asset() succeeds when called by user", () => { + it("acct-sell-asset() succeeds when called by user", () => { // arrange const amount = 1000000000000n; // sell 10000 dao tokens const dex = tokenDexContractAddress; @@ -1604,8 +1697,8 @@ describe(`public functions: ${contractName}`, () => { titleBefore: "asset map before setup", }); - // construct dao / setup smart wallet with dao tokens - setupSmartWallet(deployer); + // construct dao / setup account with dao tokens + setupAccount(deployer); dbgLog(simnet.getAssetsMap(), { titleBefore: "asset map after setup", @@ -1625,26 +1718,26 @@ describe(`public functions: ${contractName}`, () => { // act const receipt = simnet.callPublicFn( contractAddress, - "sell-asset", + "acct-sell-asset", [Cl.principal(dex), Cl.principal(asset), Cl.uint(amount)], deployer ); dbgLog(JSON.stringify(receipt, null, 2), { - titleBefore: "sell-asset receipt", + titleBefore: "acct-sell-asset receipt", }); // assert expect(receipt.result).toBeOk(Cl.bool(true)); }); - it("sell-asset() succeeds when called by agent with permission", () => { + it("acct-sell-asset() succeeds when called by agent with permission", () => { // arrange const amount = 1000000000000n; // sell 10000 dao tokens const dex = tokenDexContractAddress; const asset = daoTokenAddress; - // construct dao / setup smart wallet with dao tokens - setupSmartWallet(deployer); + // construct dao / setup account with dao tokens + setupAccount(deployer); // enable agent to buy/sell const permissionReceipt = simnet.callPublicFn( @@ -1658,7 +1751,7 @@ describe(`public functions: ${contractName}`, () => { // act const receipt = simnet.callPublicFn( contractAddress, - "sell-asset", + "acct-sell-asset", [Cl.principal(dex), Cl.principal(asset), Cl.uint(amount)], address2 // agent address ); @@ -1666,16 +1759,16 @@ describe(`public functions: ${contractName}`, () => { // assert expect(receipt.result).toBeOk(Cl.bool(true)); }); - it("sell-asset() emits the correct notification event", () => { + it("acct-sell-asset() emits the correct notification event", () => { // arrange const amount = 1000000000000n; // sell 10000 dao tokens const dex = tokenDexContractAddress; const asset = daoTokenAddress; - // construct dao / setup smart wallet with dao tokens - setupSmartWallet(deployer); + // construct dao / setup account with dao tokens + setupAccount(deployer); // build expected print event const expectedEvent = { - notification: "sell-asset", + notification: "acct-sell-asset", payload: { dexContract: dex, asset: asset, @@ -1688,7 +1781,7 @@ describe(`public functions: ${contractName}`, () => { // act const receipt = simnet.callPublicFn( contractAddress, - "sell-asset", + "acct-sell-asset", [Cl.principal(dex), Cl.principal(asset), Cl.uint(amount)], deployer ); @@ -1721,7 +1814,7 @@ describe(`read-only functions: ${contractName}`, () => { // approve the dex const approveReceipt = simnet.callPublicFn( contractAddress, - "approve-dex", + "acct-approve-dex", [Cl.principal(dex)], deployer ); @@ -1738,7 +1831,7 @@ describe(`read-only functions: ${contractName}`, () => { // revoke the dex const revokeReceipt = simnet.callPublicFn( contractAddress, - "revoke-dex", + "acct-revoke-dex", [Cl.principal(dex)], deployer ); @@ -1841,36 +1934,36 @@ describe(`read-only functions: ${contractName}`, () => { //////////////////////////////////////// it("get-configuration() returns the correct configuration", () => { // arrange - // format expected config like print event const expectedConfig = { - notification: "get-configuration", - payload: { - agent: address2, - user: deployer, - smartWallet: contractAddress, - daoToken: daoTokenAddress, - daoTokenDex: tokenDexContractAddress, - sbtcToken: SBTC_CONTRACT, - }, + account: contractAddress, + agent: address2, + owner: deployer, + daoToken: daoTokenAddress, + daoTokenDex: tokenDexContractAddress, + sbtcToken: SBTC_CONTRACT, }; // act - const config = simnet.callReadOnlyFn( + const configCV = simnet.callReadOnlyFn( contractAddress, "get-configuration", [], deployer ); + + // Convert the Clarity value to a JavaScript object + const config = configCV.result; + if (config.type !== ClarityType.Tuple) { + throw new Error("returned object is not a tuple"); + } + // Convert the TupleCV to a plain object + //console.log(`config: ${JSON.stringify(config)}`); + const configTuple = config.data; + const configData = Object.fromEntries( + Object.entries(configTuple).map( + ([key, value]: [string, ClarityValue]) => [key, cvToValue(value, true)] + ) + ); // assert - const event: ClarityEvent = { - event: "print_event", - data: { - value: Cl.tuple({ - notification: Cl.stringAscii("get-configuration"), - payload: config.result, - }), - }, - }; - const printEvent = convertSIP019PrintEvent(event); - expect(printEvent).toStrictEqual(expectedConfig); + expect(configData).toEqual(expectedConfig); }); }); diff --git a/tests/error-codes.ts b/tests/error-codes.ts index 286b1b0..6eaaf2c 100644 --- a/tests/error-codes.ts +++ b/tests/error-codes.ts @@ -142,7 +142,7 @@ export enum TokenFaktoryDexErrCode { ERR_TOKEN_NOT_AUTH = 401, } -export enum UserAgentSmartWalletErrCode { +export enum UserAgentAccountErrCode { ERR_UNAUTHORIZED = 9000, ERR_UNKNOWN_ASSET, ERR_OPERATION_FAILED,