diff --git a/README.md b/README.md index 4bc45d8..844a6bf 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,118 @@ -### Notes on state and functions in the secret contract +## Secret Network + +### Frontend and Solidity Contracts + +#### Requirements + +Before you begin, you need to install the following tools: + +- [Node (>= v18.18)](https://nodejs.org/en/download/) +- Yarn ([v1](https://classic.yarnpkg.com/en/docs/install/) or [v2+](https://yarnpkg.com/getting-started/install)) +- [Git](https://git-scm.com/downloads) + +### Quickstart + +To get started, follow the steps below: + +1. Install dependencies: + +``` +cd my-dapp-example +yarn install +``` + +2. Run a local network in the first terminal: + +Note: Use `accounts: [deployerPrivateKey]` or `accounts: { mnemonic: MNEMONIC }` in ./packages/hardhat/hardhat.config.ts + +``` +yarn chain +``` + +This command starts a local Ethereum network using Hardhat. The network runs on your local machine and can be used for testing and development. You can customize the network configuration in `packages/hardhat/hardhat.config.ts`. + +3. On a second terminal, deploy the test contract to desired network (e.g. `yarn deploy --network localhost` or `yarn deploy --network sepolia`) + +``` +yarn deploy +``` + +> Note: The contract is located in `packages/hardhat/contracts` and can be modified to suit your needs. The `yarn deploy` command uses the deploy script located in `packages/hardhat/deploy` to deploy the contract to the network. You can also customize the deploy script. + +4. On a third terminal, start the Nunya NextJS app: + +``` +yarn start +``` + +Visit app on: `http://localhost:3000`. You can interact with your smart contract using the `Debug Contracts` page. You can tweak the app config in `packages/nextjs/scaffold.config.ts`. + +Run smart contract test with `yarn hardhat:test` + +- Edit smart contracts such as `NunyaBusiness.sol` in `packages/hardhat/contracts` +- Edit frontend homepage at `packages/nextjs/app/page.tsx`. For guidance on [routing](https://nextjs.org/docs/app/building-your-application/routing/defining-routes) and configuring [pages/layouts](https://nextjs.org/docs/app/building-your-application/routing/pages-and-layouts) checkout the Next.js documentation. +- Edit deployment scripts in `packages/hardhat/deploy` + +### Setup Secret contract + +* Reference https://docs.scrt.network/secret-network-documentation/development/readme-1 + +* Install Git and Make - https://docs.scrt.network/secret-network-documentation/development/readme-1/setting-up-your-environment#install-requirements + +* Install Rust + ``` + rustup update + rustup default stable + rustup target add wasm32-unknown-unknown + source "$HOME/.cargo/env" + ``` +* Install Cargo Generate + ``` + cargo install cargo-generate --features vendored-openssl + ``` + +* Install dependencies + ``` + nvm use + npm install --global lerna + yarn set version 4.2.2 + corepack enable + corepack prepare yarn@v4.2.2 --activate + ``` + +#### Create, Compile and Deploy Contract (Example: Counter) + +* Note: To build on macOS it was necessary to run the following first as specified here https://github.com/rust-bitcoin/rust-secp256k1/issues/283#issuecomment-1590391777. Other details https://github.com/briansmith/ring/issues/1824 + +``` +/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" +brew install llvm +llvm-config --version +echo 'export AR=/opt/homebrew/opt/llvm/bin/llvm-ar' >> ~/.zshrc +echo 'export CC=/opt/homebrew/opt/llvm/bin/clang' >> ~/.zshrc +source ~/.zshrc +``` + +* Compile. Note: Outputs contract.wasm and contract.wasm.gz file in the root directory of the secret-contracts/nunya-contract folder + +``` +cd packages/secret-contracts/nunya-contract +make build +``` + +* OPTIONAL - optimize contract code. Refer to official Secret network docs + +* Upload and Instantiate +``` +yarn run secret:clean:uploadContract +yarn run secret:start:uploadContract +``` +* View logs at ./logs/instantiateOutput.log +* View on Secret Testnet block explorer at https://testnet.ping.pub/secret/ + +* Reference https://docs.scrt.network/secret-network-documentation/development/readme-1/compile-and-deploy + +### Specification: Notes on state and functions in the Secret contract #### State: @@ -56,8 +170,6 @@ secp1k256 - allows a sender of funds who wants a receipt to (optionally) receive such as `handle`, which specifies which function is being called. I have not looked into these in detail - - #### What about.. ##### storing the withdrawal address. @@ -71,23 +183,22 @@ There are no approvals, permissions or roles. The only fucntion that requires any authentication is `withdrawTo`, and the authentication is solely on the basis of the `authOut` provided when calling that function. If the user provides the correct `authOut` to map to a `balance`, then they have full control of the whole of the balance. - #### functions: - ###### new_auth_out (preferred_auth : authOut) - ``` - if preferred_auth exists already as a key in balances, then report error. - if not, then add it as a key with balance 0 and report success. +###### new_auth_out (preferred_auth : authOut) +``` +if preferred_auth exists already as a key in balances, then report error. +if not, then add it as a key with balance 0 and report success. ``` - ###### link_payment_reference (auth : authOut, payment_ref : ref) +###### link_payment_reference (auth : authOut, payment_ref : ref) ``` - if auth does not exist as a key in balances, then report error. - if not: +if auth does not exist as a key in balances, then report error. +if not: if payment_ref already exists as a key in paymentRefs, then randomly generate an alternative and set payment_ref to that. add payment_ref as a key in paymentRefs and set its value to auth ``` - ###### accept_payment (payment_ref : ref, amount : u__, encrypt_to : Option(pubkey)) +###### accept_payment (payment_ref : ref, amount : u__, encrypt_to : Option(pubkey)) ``` <<< future work: if payment_ref is encrypted with secret contract's own pubkey @@ -106,16 +217,15 @@ if it does: return the receipt and signature ``` - ###### withdraw_to (auth : authOut, amount : u__, withdrawal_address : address) +###### withdraw_to (auth : authOut, amount : u__, withdrawal_address : address) ``` - if auth does not exist as a key in balances, then report error. - if balances[auth] < amount then report error. - if neither error: +if auth does not exist as a key in balances, then report error. +if balances[auth] < amount then report error. +if neither error: return DO_THE_WITHDRAWAL (withdrawal_address, amount) ``` - ###### retrieve_pubkey () - ``` - return the secret contract's own pubkey +###### retrieve_pubkey () +``` +return the secret contract's own pubkey ``` - diff --git a/packages/hardhat/.eslintrc.json b/packages/hardhat/.eslintrc.json index 4020c1b..5d27931 100644 --- a/packages/hardhat/.eslintrc.json +++ b/packages/hardhat/.eslintrc.json @@ -5,10 +5,10 @@ "parser": "@typescript-eslint/parser", "extends": ["plugin:prettier/recommended", "plugin:@typescript-eslint/recommended"], "rules": { - "@typescript-eslint/no-unused-vars": ["warn"], + "@typescript-eslint/no-unused-vars": ["off"], "@typescript-eslint/no-explicit-any": ["off"], "prettier/prettier": [ - "warn", + "off", { "endOfLine": "auto" } diff --git a/packages/hardhat/contracts/DummyGateway.sol b/packages/hardhat/contracts/DummyGateway.sol index 85ed306..4ff2d3d 100644 --- a/packages/hardhat/contracts/DummyGateway.sol +++ b/packages/hardhat/contracts/DummyGateway.sol @@ -10,36 +10,39 @@ import "./ISecretContract.sol"; contract DummyGatewayContract is ISecretContract { function newSecretUser(string calldata secret) external returns (uint256) { - console.log("------ DummyGateway.newSecretUser", secret); + // console.log("------ DummyGateway.newSecretUser", secret); return 6; } function createPaymentReference(string calldata secret, string calldata ref) external returns (uint256) { - console.log("------ DummyGateway.createPaymentReference", secret, ref); + // console.log("------ DummyGateway.createPaymentReference", secret, ref); return 5; } - function pay(string calldata ref, uint256 amount) external returns (uint256) { - console.log("------ DummyGateway.pay", ref, amount); + // TODO: `string calldata secret` or `uint256 secret` + function pay(string calldata secret, string calldata ref, uint256 amount, string calldata denomination) external returns (uint256) { + // console.log("------ DummyGateway.pay", secret, ref, amount, denomination); return 4; } - function payWithReceipt(string calldata ref, uint256 amount, uint256 userPubkey) external returns (uint256) { - console.log("------ DummyGateway.payWithReceipt", ref, amount, userPubkey); + // TODO: `string calldata secret` or `uint256 secret` + function payWithReceipt(string calldata secret, string calldata ref, uint256 amount, string calldata denomination, uint256 userPubkey) external returns (uint256) { + // console.log("------ DummyGateway.payWithReceipt", secret, ref, amount, denomination, userPubkey); return 3; } - function withdraw(string calldata secret, uint256 amount, address withdrawalAddress) external returns (uint256) { - console.log("------ DummyGateway.withdraw", secret, amount, withdrawalAddress); + // TODO: `string calldata secret` or `uint256 secret` + function withdrawTo(string calldata secret, uint256 amount, string calldata denomination, address withdrawalAddress) external returns (uint256) { + // console.log("------ DummyGateway.withdraw", secret, amount, denomination, withdrawalAddress); return 2; } function retrievePubkey() external returns (uint256){ - console.log("------ DummyGateway.retrievePubkey"); + // console.log("------ DummyGateway.retrievePubkey"); return 1; } fallback() external payable { - console.log("----- DummyGateway.sol fallback() msg.value:", msg.value); + // console.log("----- DummyGateway.sol fallback() msg.value:", msg.value); } receive() external payable { - console.log("----- DummyGateway.sol receive() msg.value:", msg.value); + // console.log("----- DummyGateway.sol receive() msg.value:", msg.value); } } diff --git a/packages/hardhat/contracts/ISecretContract.sol b/packages/hardhat/contracts/ISecretContract.sol index df77715..daeafb3 100644 --- a/packages/hardhat/contracts/ISecretContract.sol +++ b/packages/hardhat/contracts/ISecretContract.sol @@ -5,9 +5,9 @@ pragma solidity ^0.8.0; interface ISecretContract { function newSecretUser(string calldata secret) external returns (uint256); function createPaymentReference(string calldata secret, string calldata ref) external returns (uint256); - function pay(string calldata ref, uint256 amount) external returns (uint256); - function payWithReceipt(string calldata ref, uint256 amount, uint256 userPubkey) external returns (uint256); - function withdraw(string calldata secret, uint256 amount, address withdrawalAddress) external returns (uint256); + function pay(string calldata secret, string calldata ref, uint256 amount, string calldata denomination) external returns (uint256); + function payWithReceipt(string calldata secret, string calldata ref, uint256 amount, string calldata denomination, uint256 userPubkey) external returns (uint256); + function withdrawTo(string calldata secret, uint256 amount, string calldata _denomination, address withdrawalAddress) external returns (uint256); function retrievePubkey() external returns (uint256); fallback() external payable; receive() external payable; diff --git a/packages/hardhat/contracts/NunyaBusiness.sol b/packages/hardhat/contracts/NunyaBusiness.sol index e63d373..76ca0ce 100644 --- a/packages/hardhat/contracts/NunyaBusiness.sol +++ b/packages/hardhat/contracts/NunyaBusiness.sol @@ -17,14 +17,17 @@ contract NunyaBusiness { } // payment receipt + uint16 constant SUCCESS = 0; uint16 constant ERROR_NOT_SIGNED = 1; // withdrawal uint16 constant ERROR_NO_FUNDS = 2; uint16 constant ERROR_NOT_ENOUGH_FUNDS = 3; + uint16 constant ERROR_UNKNOWN = 4; struct Receipt { uint256 paymentRef; uint256 amount; + uint256 denomination; bytes32 sig; } @@ -39,9 +42,7 @@ contract NunyaBusiness { event PaymentProcessed(uint256 requestId, uint16 code); event PaymentWithReceiptProcessed(uint256 requestId, uint16 code, Receipt receipt); event WithdrawalProcessed(uint256 requestId, uint16 code, uint256 amount); - - // see at the bottom - // event SecretNetworkError(uint256 requestId, uint16 code, string message); + event SecretNetworkError(uint256 requestId, uint16 code, string message); constructor(address payable _gateway) payable { gateway = _gateway; @@ -111,38 +112,52 @@ contract NunyaBusiness { } function createPaymentReferenceCallback(uint256 _requestId, uint16 _code, string calldata _reference) public onlyGateway validateRequest(_requestId, FunctionCallType.NEW_REF) { + if (_code != 0) { + emitSecretNetworkError(_requestId, ERROR_UNKNOWN, "Error with paymentReference - unknown"); + } + emit PaymentReferenceCreated(_requestId, _code, _reference); } - + // TODO: use ref encrypted with (user pubkey+salt) - function pay(string calldata _ref, uint256 _value) public payable returns (uint256) { + // TODO: `string calldata secret` or `uint256 secret` + function pay(string calldata _secret, string calldata _ref, uint256 _value, string calldata _denomination) public payable returns (uint256) { // >= because we need gas for fees uint256 gasPaid = fundGateway(50000); // TODO 50000 is the minimum, need to adjust to a good estimate require(msg.value >= _value + gasPaid, "Not enough value sent to pay for gas."); - uint256 requestId = secretContract.pay(_ref, msg.value - gasPaid); + uint256 requestId = secretContract.pay(_secret, _ref, msg.value - gasPaid, _denomination); expectedResult[requestId] = FunctionCallType.PAY; return(requestId); } function payCallback(uint256 _requestId, uint16 _code) public payable onlyGateway validateRequest(_requestId, FunctionCallType.PAY) { + if (_code != 0) { + emitSecretNetworkError(_requestId, ERROR_UNKNOWN, "Error with pay - unknown"); + } emit PaymentProcessed(_requestId, _code); } // TODO: use ref encrypted with (user pubkey+salt) - function payWithReceipt(string calldata _ref, uint256 _value, uint256 _userPubkey) public payable returns (uint256) { + // TODO: `string calldata secret` or `uint256 secret` + function payWithReceipt(string calldata _secret, string calldata _ref, uint256 _value, string calldata _denomination, uint256 _userPubkey) public payable returns (uint256) { uint256 gasPaid = fundGateway(50000); // TODO 50000 is the minimum, need to adjust to a good estimate require(msg.value >= _value + gasPaid, "Not enough value sent to pay for gas."); // QUESTION why is the user's pubkey required? How about the secret contact signs with it's pk and the user can validate using the secret contacts pubkey? - uint256 requestId = secretContract.payWithReceipt(_ref, msg.value - gasPaid, _userPubkey); + uint256 requestId = secretContract.payWithReceipt(_secret, _ref, msg.value - gasPaid, _denomination, _userPubkey); expectedResult[requestId] = FunctionCallType.PAY; return(requestId); } function payWithReceiptCallback(uint256 _requestId, uint16 _code , Receipt calldata _receipt) public payable onlyGateway validateRequest(_requestId, FunctionCallType.PAY) { // TODO : use ecrecover to check receipt is signed by secret contract - if (uint256(_receipt.sig) != 0) + if (uint256(_receipt.sig) != 0) { _code = ERROR_NOT_SIGNED; + emitSecretNetworkError(_requestId, ERROR_NOT_SIGNED, "Error with payWithReceipt - not signed"); + } + if (_code != 0) { + emitSecretNetworkError(_requestId, ERROR_UNKNOWN, "Error with payWithReceipt - unknown"); + } emit PaymentWithReceiptProcessed(_requestId, _code, _receipt); } @@ -162,25 +177,35 @@ contract NunyaBusiness { } // Function wrapped in secret network payload encryption - function withdrawTo(string calldata _secret, uint256 _amount, address _withdrawalAddress) public payable returns (uint256) { + // TODO: `string calldata secret` or `uint256 secret` + function withdrawTo(string calldata _secret, uint256 _amount, string calldata _denomination, address _withdrawalAddress) public payable returns (uint256) { // IDEA _amount == 0 could signal I want all funds available; alternatively, sending max value could also work require((_amount > 0), "Need to provide the amount you want to withdraw."); fundGateway(50000); // TODO 50000 is the minimum, need to adjust to a good estimate // IDEA we could store the withdrawal address in this contract instead of sending it forth and back. - uint256 requestId = secretContract.withdraw(_secret, _amount, _withdrawalAddress); + uint256 requestId = secretContract.withdrawTo(_secret, _amount, _denomination, _withdrawalAddress); // TODO: error check expectedResult[requestId] = FunctionCallType.WITHDRAW; return(requestId); } - function withdrawToCallback(uint256 _requestId, uint16 _code, uint256 _amount, address payable _withdrawalAddress) onlyGateway validateRequest(_requestId, FunctionCallType.WITHDRAW) public { + function withdrawToCallback(uint256 _requestId, uint16 _code, uint256 _amount, string calldata _denomination, address payable _withdrawalAddress) onlyGateway validateRequest(_requestId, FunctionCallType.WITHDRAW) public { + // TODO: handle returning more specific errors in Secret contract if (_code == 0 && _amount == 0) { _code = ERROR_NO_FUNDS; + emitSecretNetworkError(_requestId, ERROR_NO_FUNDS, "Error with withdraw - no funds"); + } + if (_code != 0) { + emitSecretNetworkError(_requestId, ERROR_UNKNOWN, "Error with withdraw - unknown"); } - if(_amount > 0) + if (_code == 0 && _amount > 0) { + // TODO: only if the `_denomination` is "ETH"? _withdrawalAddress.transfer(_amount); - emit WithdrawalProcessed(_requestId, _code, _amount); + emit WithdrawalProcessed(_requestId, _code, _amount); + } else { + emitSecretNetworkError(_requestId, ERROR_UNKNOWN, "Error with withdraw - transfer"); + } } function fundGateway(uint256 keepGas) internal returns (uint256) { @@ -216,8 +241,7 @@ contract NunyaBusiness { return string(bstr); } - // TODO What's the exact use case? Or should instead the secret contract always call the callback with an appropriate error code? - // function emitSecretNetworkError(uint256 _requestId, uint16 _code, string memory _message) public onlyGateway { - // emit SecretNetworkError(_requestId, _code, _message); - // } + function emitSecretNetworkError(uint256 _requestId, uint16 _code, string memory _message) public onlyGateway { + emit SecretNetworkError(_requestId, _code, _message); + } } diff --git a/packages/hardhat/hardhat.config.ts b/packages/hardhat/hardhat.config.ts index 0f39290..cbe737b 100644 --- a/packages/hardhat/hardhat.config.ts +++ b/packages/hardhat/hardhat.config.ts @@ -10,8 +10,10 @@ import "@nomicfoundation/hardhat-verify"; import "hardhat-deploy"; import "hardhat-deploy-ethers"; +// https://dashboard.alchemyapi.io +const FALLBACK_ALCHEMY_API_KEY = "oKxs-03sij-U_N0iOlrSsZFr29-IqbuF"; const providerRpcUrl = process.env.PROVIDER_RPC; -const providerApiKey = process.env.GETBLOCK_API_KEY; +const providerApiKey = process.env.GETBLOCK_API_KEY || process.env.ALCHEMY_API_KEY || FALLBACK_ALCHEMY_API_KEY; // If not set, it uses ours Alchemy's default API key, which doesn't work (gives ProviderError: The team owning this app is inactive. Please contact support at https://dashboard.alchemyapi.io/support) // You can get your own at https://dashboard.alchemyapi.io. @@ -67,8 +69,8 @@ const config: HardhatUserConfig = { sepolia: { chainId: 11155111, url: `${providerRpcUrl || "https://eth-sepolia.g.alchemy.com/v2/"}${providerApiKey}`, - accounts: { mnemonic: MNEMONIC }, - // accounts: [deployerPrivateKey], + // accounts: { mnemonic: MNEMONIC }, + accounts: [deployerPrivateKey], }, arbitrum: { url: `https://arb-mainnet.g.alchemy.com/v2/${providerApiKey}`, diff --git a/packages/nextjs/.eslintrc.json b/packages/nextjs/.eslintrc.json index c120c8c..c200587 100644 --- a/packages/nextjs/.eslintrc.json +++ b/packages/nextjs/.eslintrc.json @@ -2,11 +2,11 @@ "parser": "@typescript-eslint/parser", "extends": ["next/core-web-vitals", "plugin:prettier/recommended", "plugin:@typescript-eslint/recommended"], "rules": { - "@typescript-eslint/no-unused-vars": ["error"], + "@typescript-eslint/no-unused-vars": ["off"], "@typescript-eslint/no-explicit-any": ["off"], "@typescript-eslint/ban-ts-comment": ["off"], "prettier/prettier": [ - "warn", + "off", { "endOfLine": "auto" } diff --git a/packages/nextjs/app/pay/[paymentReference]/[amount]/[currency]/page.tsx b/packages/nextjs/app/pay/[paymentReference]/[amount]/[currency]/page.tsx index 752e049..bca2443 100644 --- a/packages/nextjs/app/pay/[paymentReference]/[amount]/[currency]/page.tsx +++ b/packages/nextjs/app/pay/[paymentReference]/[amount]/[currency]/page.tsx @@ -33,6 +33,7 @@ const PaymentPage: NextPage = ({ params }: PageProps) => { const { targetNetwork } = useTargetNetwork(); // const encoder: TextEncoder = new global.TextEncoder(); + // eslint-disable-next-line react-hooks/exhaustive-deps useEffect(() => { setReference(paymentReferenceParam); diff --git a/packages/nextjs/app/withdraw.tsx b/packages/nextjs/app/withdraw.tsx index 68e5239..ed7ff9d 100644 --- a/packages/nextjs/app/withdraw.tsx +++ b/packages/nextjs/app/withdraw.tsx @@ -7,7 +7,7 @@ import { convertToBigint } from "~~/utils/convert"; interface WithdrawalRequest { amount: string; - address: string; + address: bigint; } const Withdraw: NextPage = () => { @@ -28,13 +28,13 @@ const Withdraw: NextPage = () => { const requestId = await writeContractAsync({ functionName: "withdrawTo", // TODO args: [encoder.encode(secret) ... - args: [secret, parseEther(amount), address], + args: [secret, parseEther(amount), convertToBigint(address), "ETH"], }); console.log("⚡ Requesting new account", requestId, secret, parseEther(amount), address); if (!requestId) { return console.error("No request ID returned."); } - openRequests.set(convertToBigint(requestId), { amount, address }); + openRequests.set(convertToBigint(requestId), { amount, address: convertToBigint(address) }); }; useScaffoldWatchContractEvent({ diff --git a/packages/nextjs/contracts/deployedContracts.ts b/packages/nextjs/contracts/deployedContracts.ts index 43b4aae..f795c4e 100644 --- a/packages/nextjs/contracts/deployedContracts.ts +++ b/packages/nextjs/contracts/deployedContracts.ts @@ -7,7 +7,7 @@ import { GenericContractsDeclaration } from "~~/utils/scaffold-eth/contract"; const deployedContracts = { 31337: { DummyGatewayContract: { - address: "0x9A9f2CCfdE556A7E9Ff0848998Aa4a0CFD8863AE", + address: "0x5FbDB2315678afecb367f032d93F642f64180aa3", abi: [ { stateMutability: "payable", @@ -58,6 +58,11 @@ const deployedContracts = { }, { inputs: [ + { + internalType: "string", + name: "secret", + type: "string", + }, { internalType: "string", name: "ref", @@ -68,6 +73,11 @@ const deployedContracts = { name: "amount", type: "uint256", }, + { + internalType: "uint256", + name: "denomination", + type: "uint256", + }, ], name: "pay", outputs: [ @@ -82,6 +92,11 @@ const deployedContracts = { }, { inputs: [ + { + internalType: "string", + name: "secret", + type: "string", + }, { internalType: "string", name: "ref", @@ -92,6 +107,11 @@ const deployedContracts = { name: "amount", type: "uint256", }, + { + internalType: "uint256", + name: "denomination", + type: "uint256", + }, { internalType: "uint256", name: "userPubkey", @@ -134,13 +154,18 @@ const deployedContracts = { name: "amount", type: "uint256", }, + { + internalType: "uint256", + name: "denomination", + type: "uint256", + }, { internalType: "address", name: "withdrawalAddress", type: "address", }, ], - name: "withdraw", + name: "withdrawTo", outputs: [ { internalType: "uint256", @@ -159,7 +184,7 @@ const deployedContracts = { inheritedFunctions: {}, }, NunyaBusiness: { - address: "0x3Aa5ebB10DC797CAC828524e59A333d0A371443c", + address: "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0", abi: [ { inputs: [ @@ -262,6 +287,11 @@ const deployedContracts = { name: "amount", type: "uint256", }, + { + internalType: "uint256", + name: "denomination", + type: "uint256", + }, { internalType: "bytes32", name: "sig", @@ -277,6 +307,31 @@ const deployedContracts = { name: "PaymentWithReceiptProcessed", type: "event", }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "requestId", + type: "uint256", + }, + { + indexed: false, + internalType: "uint16", + name: "code", + type: "uint16", + }, + { + indexed: false, + internalType: "string", + name: "message", + type: "string", + }, + ], + name: "SecretNetworkError", + type: "event", + }, { anonymous: false, inputs: [ @@ -353,6 +408,29 @@ const deployedContracts = { stateMutability: "nonpayable", type: "function", }, + { + inputs: [ + { + internalType: "uint256", + name: "_requestId", + type: "uint256", + }, + { + internalType: "uint16", + name: "_code", + type: "uint16", + }, + { + internalType: "string", + name: "_message", + type: "string", + }, + ], + name: "emitSecretNetworkError", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, { inputs: [ { @@ -392,6 +470,11 @@ const deployedContracts = { }, { inputs: [ + { + internalType: "string", + name: "_secret", + type: "string", + }, { internalType: "string", name: "_ref", @@ -399,7 +482,12 @@ const deployedContracts = { }, { internalType: "uint256", - name: "_amount", + name: "_value", + type: "uint256", + }, + { + internalType: "uint256", + name: "_denomination", type: "uint256", }, ], @@ -434,6 +522,11 @@ const deployedContracts = { }, { inputs: [ + { + internalType: "string", + name: "_secret", + type: "string", + }, { internalType: "string", name: "_ref", @@ -441,7 +534,12 @@ const deployedContracts = { }, { internalType: "uint256", - name: "_amount", + name: "_value", + type: "uint256", + }, + { + internalType: "uint256", + name: "_denomination", type: "uint256", }, { @@ -485,6 +583,11 @@ const deployedContracts = { name: "amount", type: "uint256", }, + { + internalType: "uint256", + name: "denomination", + type: "uint256", + }, { internalType: "bytes32", name: "sig", @@ -531,6 +634,11 @@ const deployedContracts = { name: "_amount", type: "uint256", }, + { + internalType: "uint256", + name: "_denomination", + type: "uint256", + }, { internalType: "address", name: "_withdrawalAddress", @@ -565,6 +673,11 @@ const deployedContracts = { name: "_amount", type: "uint256", }, + { + internalType: "uint256", + name: "_denomination", + type: "uint256", + }, { internalType: "address payable", name: "_withdrawalAddress", @@ -583,145 +696,6 @@ const deployedContracts = { ], inheritedFunctions: {}, }, - SecretContract: { - address: "0xD6c6E4849B7b059986693A7756f1DB518B669911", - abi: [ - { - inputs: [ - { - internalType: "uint256", - name: "secret", - type: "uint256", - }, - { - internalType: "string", - name: "ref", - type: "string", - }, - ], - name: "linkPaymentRef", - outputs: [ - { - internalType: "uint256", - name: "", - type: "uint256", - }, - ], - stateMutability: "nonpayable", - type: "function", - }, - { - inputs: [ - { - internalType: "uint256", - name: "secret", - type: "uint256", - }, - ], - name: "newSecretUser", - outputs: [ - { - internalType: "uint256", - name: "", - type: "uint256", - }, - ], - stateMutability: "nonpayable", - type: "function", - }, - { - inputs: [ - { - internalType: "string", - name: "ref", - type: "string", - }, - { - internalType: "uint256", - name: "amount", - type: "uint256", - }, - ], - name: "pay", - outputs: [ - { - internalType: "uint256", - name: "", - type: "uint256", - }, - ], - stateMutability: "nonpayable", - type: "function", - }, - { - inputs: [ - { - internalType: "string", - name: "ref", - type: "string", - }, - { - internalType: "uint256", - name: "amount", - type: "uint256", - }, - { - internalType: "uint256", - name: "userPubkey", - type: "uint256", - }, - ], - name: "payWithReceipt", - outputs: [ - { - internalType: "uint256", - name: "", - type: "uint256", - }, - ], - stateMutability: "nonpayable", - type: "function", - }, - { - inputs: [], - name: "retrievePubkey", - outputs: [ - { - internalType: "uint256", - name: "", - type: "uint256", - }, - ], - stateMutability: "nonpayable", - type: "function", - }, - { - inputs: [ - { - internalType: "string", - name: "secret", - type: "string", - }, - { - internalType: "address", - name: "withdrawalAddress", - type: "address", - }, - ], - name: "withdraw", - outputs: [ - { - internalType: "uint256", - name: "", - type: "uint256", - }, - ], - stateMutability: "nonpayable", - type: "function", - }, - ], - inheritedFunctions: {}, - }, }, } as const; diff --git a/packages/secret-contracts/nunya-contract/Cargo.lock b/packages/secret-contracts/nunya-contract/Cargo.lock index 7c4e524..6fcbc9b 100644 --- a/packages/secret-contracts/nunya-contract/Cargo.lock +++ b/packages/secret-contracts/nunya-contract/Cargo.lock @@ -22,6 +22,12 @@ dependencies = [ "version_check", ] +[[package]] +name = "anybuf" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb5f1dee23caf80904249463cc4493b6789c2250f88c8f8d9160de5c6099bfe7" + [[package]] name = "base16ct" version = "0.1.1" @@ -751,6 +757,7 @@ dependencies = [ name = "secret_evm_storage" version = "0.1.0" dependencies = [ + "anybuf", "base64 0.22.0", "cosmwasm-schema", "schemars", diff --git a/packages/secret-contracts/nunya-contract/cargo.toml b/packages/secret-contracts/nunya-contract/cargo.toml index a410766..4fb93ef 100644 --- a/packages/secret-contracts/nunya-contract/cargo.toml +++ b/packages/secret-contracts/nunya-contract/cargo.toml @@ -29,7 +29,7 @@ schema = ["cosmwasm-schema"] [dependencies] cosmwasm-schema = { version = "2.0.0", optional = true } -cosmwasm-std = { package = "secret-cosmwasm-std", version = "1.0.0" } +cosmwasm-std = { package = "secret-cosmwasm-std", version = "1.1.10", features = ["stargate"] } cosmwasm-storage = { package = "secret-cosmwasm-storage", version = "1.0.0" } schemars = "0.8.11" secret-toolkit = { version = "0.10.0", default-features = false, features = [ @@ -48,6 +48,7 @@ secret-toolkit-serialization = { version = "0.10.0", features = ["base64"] } # thiserror = { version = "1.0.31" } tnls = { git = "https://github.com/SecretSaturn/TNLS", branch = "main", package = "secret_gateway", default-features = false } # cw-storage-plus = { version = "0.14.0", default-features = false } +anybuf = {version = "0.5.0"} [[bin]] name = "schema" diff --git a/packages/secret-contracts/nunya-contract/node/.env.example b/packages/secret-contracts/nunya-contract/node/.env.example deleted file mode 100644 index e29a6d9..0000000 --- a/packages/secret-contracts/nunya-contract/node/.env.example +++ /dev/null @@ -1,4 +0,0 @@ -# FIXME - update these after deploying nunya-contract -MNEMONIC="shed clerk pray velvet flower tide bug idea private solar prize tackle" -CODE_HASH="e8d3f1c82b620fced20a7d8878ea81cd5af3de28ad7427246c3d7e93b2fa3c4f" -SECRET_ADDRESS="secret1m9d45wakl6vmshxc5kp6ztrf29uc3gzm8vpe47" diff --git a/packages/secret-contracts/nunya-contract/node/.gitignore b/packages/secret-contracts/nunya-contract/node/.gitignore deleted file mode 100644 index 1c0d0e5..0000000 --- a/packages/secret-contracts/nunya-contract/node/.gitignore +++ /dev/null @@ -1,21 +0,0 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. - -# dependencies -/node_modules -/node_modules* -/.pnp -.pnp.js - -# testing -/coverage - -# production -/build - -# misc - -.env - -npm-debug.log* -yarn-debug.log* -yarn-error.log* \ No newline at end of file diff --git a/packages/secret-contracts/nunya-contract/node/package-lock.json b/packages/secret-contracts/nunya-contract/node/package-lock.json deleted file mode 100644 index d22a529..0000000 --- a/packages/secret-contracts/nunya-contract/node/package-lock.json +++ /dev/null @@ -1,1484 +0,0 @@ -{ - "name": "node", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "node", - "version": "1.0.0", - "license": "ISC", - "dependencies": { - "@solar-republic/cosmos-grpc": "^0.14.2", - "@solar-republic/neutrino": "^1.0.8", - "dotenv": "^16.4.5", - "ethers": "^5.7.2", - "secretjs": "^1.12.4", - "secure-random": "^1.1.2" - } - }, - "node_modules/@blake.regalia/belt": { - "version": "0.31.1", - "resolved": "https://registry.npmjs.org/@blake.regalia/belt/-/belt-0.31.1.tgz", - "integrity": "sha512-VuL8sfhn+lYGAow5xht5jjV75k0CfudZpWI0IWdgc2uj20X6UfdLdq4BuA6CAnVEkyWb/NVhU6cs1o5TWtzS0A==" - }, - "node_modules/@cosmjs/encoding": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@cosmjs/encoding/-/encoding-0.27.1.tgz", - "integrity": "sha512-rayLsA0ojHeniaRfWWcqSsrE/T1rl1gl0OXVNtXlPwLJifKBeLEefGbOUiAQaT0wgJ8VNGBazVtAZBpJidfDhw==", - "dependencies": { - "base64-js": "^1.3.0", - "bech32": "^1.1.4", - "readonly-date": "^1.0.0" - } - }, - "node_modules/@cosmjs/encoding/node_modules/bech32": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", - "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==" - }, - "node_modules/@cosmjs/math": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/@cosmjs/math/-/math-0.27.1.tgz", - "integrity": "sha512-cHWVjmfIjtRc7f80n7x+J5k8pe+vTVTQ0lA82tIxUgqUvgS6rogPP/TmGtTiZ4+NxWxd11DUISY6gVpr18/VNQ==", - "dependencies": { - "bn.js": "^5.2.0" - } - }, - "node_modules/@ethersproject/abi": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.7.0.tgz", - "integrity": "sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/address": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/hash": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/strings": "^5.7.0" - } - }, - "node_modules/@ethersproject/abstract-provider": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz", - "integrity": "sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/networks": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "@ethersproject/web": "^5.7.0" - } - }, - "node_modules/@ethersproject/abstract-signer": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz", - "integrity": "sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/abstract-provider": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0" - } - }, - "node_modules/@ethersproject/address": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.7.0.tgz", - "integrity": "sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/rlp": "^5.7.0" - } - }, - "node_modules/@ethersproject/base64": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.7.0.tgz", - "integrity": "sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0" - } - }, - "node_modules/@ethersproject/basex": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.7.0.tgz", - "integrity": "sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/properties": "^5.7.0" - } - }, - "node_modules/@ethersproject/bignumber": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.7.0.tgz", - "integrity": "sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "bn.js": "^5.2.1" - } - }, - "node_modules/@ethersproject/bytes": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.7.0.tgz", - "integrity": "sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/constants": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.7.0.tgz", - "integrity": "sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bignumber": "^5.7.0" - } - }, - "node_modules/@ethersproject/contracts": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.7.0.tgz", - "integrity": "sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/abi": "^5.7.0", - "@ethersproject/abstract-provider": "^5.7.0", - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/transactions": "^5.7.0" - } - }, - "node_modules/@ethersproject/hash": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.7.0.tgz", - "integrity": "sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/base64": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/strings": "^5.7.0" - } - }, - "node_modules/@ethersproject/hdnode": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.7.0.tgz", - "integrity": "sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/basex": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/pbkdf2": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/sha2": "^5.7.0", - "@ethersproject/signing-key": "^5.7.0", - "@ethersproject/strings": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "@ethersproject/wordlists": "^5.7.0" - } - }, - "node_modules/@ethersproject/json-wallets": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz", - "integrity": "sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/hdnode": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/pbkdf2": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/random": "^5.7.0", - "@ethersproject/strings": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "aes-js": "3.0.0", - "scrypt-js": "3.0.1" - } - }, - "node_modules/@ethersproject/keccak256": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.7.0.tgz", - "integrity": "sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "js-sha3": "0.8.0" - } - }, - "node_modules/@ethersproject/logger": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.7.0.tgz", - "integrity": "sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ] - }, - "node_modules/@ethersproject/networks": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.7.1.tgz", - "integrity": "sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/pbkdf2": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz", - "integrity": "sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/sha2": "^5.7.0" - } - }, - "node_modules/@ethersproject/properties": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.7.0.tgz", - "integrity": "sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/providers": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.7.2.tgz", - "integrity": "sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/abstract-provider": "^5.7.0", - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/base64": "^5.7.0", - "@ethersproject/basex": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/hash": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/networks": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/random": "^5.7.0", - "@ethersproject/rlp": "^5.7.0", - "@ethersproject/sha2": "^5.7.0", - "@ethersproject/strings": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "@ethersproject/web": "^5.7.0", - "bech32": "1.1.4", - "ws": "7.4.6" - } - }, - "node_modules/@ethersproject/providers/node_modules/bech32": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", - "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==" - }, - "node_modules/@ethersproject/random": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.7.0.tgz", - "integrity": "sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/rlp": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.7.0.tgz", - "integrity": "sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/sha2": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.7.0.tgz", - "integrity": "sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "hash.js": "1.1.7" - } - }, - "node_modules/@ethersproject/signing-key": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.7.0.tgz", - "integrity": "sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "bn.js": "^5.2.1", - "elliptic": "6.5.4", - "hash.js": "1.1.7" - } - }, - "node_modules/@ethersproject/solidity": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.7.0.tgz", - "integrity": "sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/sha2": "^5.7.0", - "@ethersproject/strings": "^5.7.0" - } - }, - "node_modules/@ethersproject/strings": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.7.0.tgz", - "integrity": "sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/transactions": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.7.0.tgz", - "integrity": "sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/address": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/rlp": "^5.7.0", - "@ethersproject/signing-key": "^5.7.0" - } - }, - "node_modules/@ethersproject/units": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.7.0.tgz", - "integrity": "sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/logger": "^5.7.0" - } - }, - "node_modules/@ethersproject/wallet": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.7.0.tgz", - "integrity": "sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/abstract-provider": "^5.7.0", - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/hash": "^5.7.0", - "@ethersproject/hdnode": "^5.7.0", - "@ethersproject/json-wallets": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/random": "^5.7.0", - "@ethersproject/signing-key": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "@ethersproject/wordlists": "^5.7.0" - } - }, - "node_modules/@ethersproject/web": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.7.1.tgz", - "integrity": "sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/base64": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/strings": "^5.7.0" - } - }, - "node_modules/@ethersproject/wordlists": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.7.0.tgz", - "integrity": "sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/hash": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/strings": "^5.7.0" - } - }, - "node_modules/@noble/hashes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.0.0.tgz", - "integrity": "sha512-DZVbtY62kc3kkBtMHqwCOfXrT/hnoORy5BJ4+HU1IR59X0KWAOqsfzQPcUl/lQLlG7qXbe/fZ3r/emxtAl+sqg==" - }, - "node_modules/@noble/secp256k1": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.0.tgz", - "integrity": "sha512-kbacwGSsH/CTout0ZnZWxnW1B+jH/7r/WAAKLBtrRJ/+CUH7lgmQzl3GTrQua3SGKWNSDsS6lmjnDpIJ5Dxyaw==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ] - }, - "node_modules/@protobufjs/aspromise": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" - }, - "node_modules/@protobufjs/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" - }, - "node_modules/@protobufjs/codegen": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" - }, - "node_modules/@protobufjs/eventemitter": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" - }, - "node_modules/@protobufjs/fetch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", - "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", - "dependencies": { - "@protobufjs/aspromise": "^1.1.1", - "@protobufjs/inquire": "^1.1.0" - } - }, - "node_modules/@protobufjs/float": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" - }, - "node_modules/@protobufjs/inquire": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" - }, - "node_modules/@protobufjs/path": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" - }, - "node_modules/@protobufjs/pool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" - }, - "node_modules/@protobufjs/utf8": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" - }, - "node_modules/@solar-republic/cosmos-grpc": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/@solar-republic/cosmos-grpc/-/cosmos-grpc-0.14.2.tgz", - "integrity": "sha512-Q74TXtwUM2J5lvs3MnK1uH9+Wx4DFAyekEpOo0nvkPMh/0JRCdSFPZywWezNi//QVenVHXF2DK1V49UBHPoNyg==", - "dependencies": { - "@solar-republic/crypto": "^0.2.5", - "google-protobuf": "^3.21.2", - "protobufjs": "^7.2.6" - }, - "bin": { - "protoc-gen-secret": "build/protoc/run.js" - } - }, - "node_modules/@solar-republic/cosmos-grpc/node_modules/@types/node": { - "version": "20.11.24", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.24.tgz", - "integrity": "sha512-Kza43ewS3xoLgCEpQrsT+xRo/EJej1y0kVYGiLFE1NEODXGzTfwiC6tXTLMQskn1X4/Rjlh0MQUvx9W+L9long==", - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/@solar-republic/cosmos-grpc/node_modules/protobufjs": { - "version": "7.2.6", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.6.tgz", - "integrity": "sha512-dgJaEDDL6x8ASUZ1YqWciTRrdOuYNzoOf27oHNfdyvKqHr5i0FV7FSLU+aIeFjyFgVxrpTOtQUi0BLLBymZaBw==", - "hasInstallScript": true, - "dependencies": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.4", - "@protobufjs/eventemitter": "^1.1.0", - "@protobufjs/fetch": "^1.1.0", - "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.0", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.0", - "@types/node": ">=13.7.0", - "long": "^5.0.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@solar-republic/crypto": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/@solar-republic/crypto/-/crypto-0.2.5.tgz", - "integrity": "sha512-ofEsb/AHd6f3dldb93miRBfF8yUnXf3a2k0nJh2eDIP6lK0VxjKwRO3U95xya+nHPLYPJvseh7GMsTAEzbmbPQ==", - "dependencies": { - "@blake.regalia/belt": "^0.31.1", - "@cosmjs/encoding": "^0.32.2", - "@solar-republic/wasm-secp256k1": "^0.2.2", - "hash-wasm": "^4.11.0" - } - }, - "node_modules/@solar-republic/crypto/node_modules/@cosmjs/encoding": { - "version": "0.32.2", - "resolved": "https://registry.npmjs.org/@cosmjs/encoding/-/encoding-0.32.2.tgz", - "integrity": "sha512-WX7m1wLpA9V/zH0zRcz4EmgZdAv1F44g4dbXOgNj1eXZw1PIGR12p58OEkLN51Ha3S4DKRtCv5CkhK1KHEvQtg==", - "dependencies": { - "base64-js": "^1.3.0", - "bech32": "^1.1.4", - "readonly-date": "^1.0.0" - } - }, - "node_modules/@solar-republic/crypto/node_modules/bech32": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", - "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==" - }, - "node_modules/@solar-republic/neutrino": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@solar-republic/neutrino/-/neutrino-1.0.8.tgz", - "integrity": "sha512-jvixdoLJrxbaZTQzvXFmTabYLzw2H159kTxxDIa1cXIiNyFHBLr3JwTmxJXBO8jynib2k4O0J2GTMfpa6CwLAg==", - "dependencies": { - "@blake.regalia/belt": "^0.31.1" - } - }, - "node_modules/@solar-republic/wasm-secp256k1": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@solar-republic/wasm-secp256k1/-/wasm-secp256k1-0.2.2.tgz", - "integrity": "sha512-knCVLxIbWw0v/T+qBU5MUpECqkyrbRJIQC4ORAvTRm4O4w1gjxCbrdG0WPd1hZDWYItAlwYh+3LJF7t+tRqjjQ==", - "dependencies": { - "@blake.regalia/belt": "^0.31.0" - } - }, - "node_modules/@types/node": { - "version": "10.12.18", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz", - "integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==" - }, - "node_modules/aes-js": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", - "integrity": "sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==" - }, - "node_modules/base-x": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", - "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/bech32": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/bech32/-/bech32-2.0.0.tgz", - "integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==" - }, - "node_modules/big-integer": { - "version": "1.6.51", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", - "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/bignumber.js": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.2.tgz", - "integrity": "sha512-GAcQvbpsM0pUb0zw1EI0KhQEZ+lRwR5fYaAp3vPOYuP7aDvGy6cVN6XHLauvF8SOga2y0dcLcjt3iQDTSEliyw==", - "engines": { - "node": "*" - } - }, - "node_modules/bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dependencies": { - "file-uri-to-path": "1.0.0" - } - }, - "node_modules/bip32": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/bip32/-/bip32-2.0.6.tgz", - "integrity": "sha512-HpV5OMLLGTjSVblmrtYRfFFKuQB+GArM0+XP8HGWfJ5vxYBqo+DesvJwOdC2WJ3bCkZShGf0QIfoIpeomVzVdA==", - "dependencies": { - "@types/node": "10.12.18", - "bs58check": "^2.1.1", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "tiny-secp256k1": "^1.1.3", - "typeforce": "^1.11.5", - "wif": "^2.0.6" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/bip39": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/bip39/-/bip39-3.0.4.tgz", - "integrity": "sha512-YZKQlb752TrUWqHWj7XAwCSjYEgGAk+/Aas3V7NyjQeZYsztO8JnQUaCWhcnL4T+jL8nvB8typ2jRPzTlgugNw==", - "dependencies": { - "@types/node": "11.11.6", - "create-hash": "^1.1.0", - "pbkdf2": "^3.0.9", - "randombytes": "^2.0.1" - } - }, - "node_modules/bip39/node_modules/@types/node": { - "version": "11.11.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-11.11.6.tgz", - "integrity": "sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ==" - }, - "node_modules/bn.js": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", - "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==" - }, - "node_modules/brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==" - }, - "node_modules/bs58": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", - "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", - "dependencies": { - "base-x": "^3.0.2" - } - }, - "node_modules/bs58check": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", - "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", - "dependencies": { - "bs58": "^4.0.0", - "create-hash": "^1.1.0", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "dependencies": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "node_modules/create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "dependencies": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "node_modules/cross-fetch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", - "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", - "dependencies": { - "node-fetch": "2.6.7" - } - }, - "node_modules/curve25519-js": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/curve25519-js/-/curve25519-js-0.0.4.tgz", - "integrity": "sha512-axn2UMEnkhyDUPWOwVKBMVIzSQy2ejH2xRGy1wq81dqRwApXfIzfbE3hIX0ZRFBIihf/KDqK158DLwESu4AK1w==" - }, - "node_modules/dotenv": { - "version": "16.4.5", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", - "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "node_modules/elliptic": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", - "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", - "dependencies": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/elliptic/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - }, - "node_modules/ethers": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", - "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "dependencies": { - "@ethersproject/abi": "5.7.0", - "@ethersproject/abstract-provider": "5.7.0", - "@ethersproject/abstract-signer": "5.7.0", - "@ethersproject/address": "5.7.0", - "@ethersproject/base64": "5.7.0", - "@ethersproject/basex": "5.7.0", - "@ethersproject/bignumber": "5.7.0", - "@ethersproject/bytes": "5.7.0", - "@ethersproject/constants": "5.7.0", - "@ethersproject/contracts": "5.7.0", - "@ethersproject/hash": "5.7.0", - "@ethersproject/hdnode": "5.7.0", - "@ethersproject/json-wallets": "5.7.0", - "@ethersproject/keccak256": "5.7.0", - "@ethersproject/logger": "5.7.0", - "@ethersproject/networks": "5.7.1", - "@ethersproject/pbkdf2": "5.7.0", - "@ethersproject/properties": "5.7.0", - "@ethersproject/providers": "5.7.2", - "@ethersproject/random": "5.7.0", - "@ethersproject/rlp": "5.7.0", - "@ethersproject/sha2": "5.7.0", - "@ethersproject/signing-key": "5.7.0", - "@ethersproject/solidity": "5.7.0", - "@ethersproject/strings": "5.7.0", - "@ethersproject/transactions": "5.7.0", - "@ethersproject/units": "5.7.0", - "@ethersproject/wallet": "5.7.0", - "@ethersproject/web": "5.7.1", - "@ethersproject/wordlists": "5.7.0" - } - }, - "node_modules/file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" - }, - "node_modules/google-protobuf": { - "version": "3.21.2", - "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.21.2.tgz", - "integrity": "sha512-3MSOYFO5U9mPGikIYCzK0SaThypfGgS6bHqrUGXG3DPHCrb+txNqeEcns1W0lkGfk0rCyNXm7xB9rMxnCiZOoA==" - }, - "node_modules/hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", - "dependencies": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/hash-wasm": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/hash-wasm/-/hash-wasm-4.11.0.tgz", - "integrity": "sha512-HVusNXlVqHe0fzIzdQOGolnFN6mX/fqcrSAOcTBXdvzrXVHwTz11vXeKRmkR5gTuwVpvHZEIyKoePDvuAR+XwQ==" - }, - "node_modules/hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "node_modules/hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", - "dependencies": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/js-sha3": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", - "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" - }, - "node_modules/long": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", - "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" - }, - "node_modules/md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" - }, - "node_modules/minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==" - }, - "node_modules/miscreant": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/miscreant/-/miscreant-0.3.2.tgz", - "integrity": "sha512-fL9KxsQz9BJB2KGPMHFrReioywkiomBiuaLk6EuChijK0BsJsIKJXdVomR+/bPj5mvbFD6wM0CM3bZio9g7OHA==" - }, - "node_modules/nan": { - "version": "2.18.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.18.0.tgz", - "integrity": "sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==" - }, - "node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/pako": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pako/-/pako-2.0.4.tgz", - "integrity": "sha512-v8tweI900AUkZN6heMU/4Uy4cXRc2AYNRggVmTR+dEncawDJgCdLMximOVA2p4qO57WMynangsfGRb5WD6L1Bg==" - }, - "node_modules/pbkdf2": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", - "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", - "dependencies": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/protobufjs": { - "version": "7.2.5", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.5.tgz", - "integrity": "sha512-gGXRSXvxQ7UiPgfw8gevrfRWcTlSbOFg+p/N+JVJEK5VhueL2miT6qTymqAmjr1Q5WbOCyJbyrk6JfWKwlFn6A==", - "hasInstallScript": true, - "dependencies": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.4", - "@protobufjs/eventemitter": "^1.1.0", - "@protobufjs/fetch": "^1.1.0", - "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.0", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.0", - "@types/node": ">=13.7.0", - "long": "^5.0.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/protobufjs/node_modules/@types/node": { - "version": "20.11.24", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.24.tgz", - "integrity": "sha512-Kza43ewS3xoLgCEpQrsT+xRo/EJej1y0kVYGiLFE1NEODXGzTfwiC6tXTLMQskn1X4/Rjlh0MQUvx9W+L9long==", - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readonly-date": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/readonly-date/-/readonly-date-1.0.0.tgz", - "integrity": "sha512-tMKIV7hlk0h4mO3JTmmVuIlJVXjKk3Sep9Bf5OH0O+758ruuVkUy2J9SttDLm91IEX/WHlXPSpxMGjPj4beMIQ==" - }, - "node_modules/ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/scrypt-js": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz", - "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==" - }, - "node_modules/secretjs": { - "version": "1.12.4", - "resolved": "https://registry.npmjs.org/secretjs/-/secretjs-1.12.4.tgz", - "integrity": "sha512-DH16hYTPa4NNxo1T/tY2GyJRte7rgp5kRy8k1pwaPK59WtbQdTBdPQQsEI2L5T7NDVEUXbdbTqyQkt5usN4KcQ==", - "dependencies": { - "@cosmjs/encoding": "0.27.1", - "@cosmjs/math": "0.27.1", - "@noble/hashes": "1.0.0", - "@noble/secp256k1": "1.7.0", - "bech32": "2.0.0", - "big-integer": "1.6.51", - "bignumber.js": "9.0.2", - "bip32": "2.0.6", - "bip39": "3.0.4", - "cross-fetch": "3.1.5", - "curve25519-js": "0.0.4", - "google-protobuf": "^3.14.0", - "miscreant": "0.3.2", - "pako": "2.0.4", - "protobufjs": "7.2.5", - "secure-random": "1.1.2" - } - }, - "node_modules/secure-random": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/secure-random/-/secure-random-1.1.2.tgz", - "integrity": "sha512-H2bdSKERKdBV1SwoqYm6C0y+9EA94v6SUBOWO8kDndc4NoUih7Dv6Tsgma7zO1lv27wIvjlD0ZpMQk7um5dheQ==" - }, - "node_modules/sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - }, - "bin": { - "sha.js": "bin.js" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/tiny-secp256k1": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-1.1.6.tgz", - "integrity": "sha512-FmqJZGduTyvsr2cF3375fqGHUovSwDi/QytexX1Se4BPuPZpTE5Ftp5fg+EFSuEf3lhZqgCRjEG3ydUQ/aNiwA==", - "hasInstallScript": true, - "dependencies": { - "bindings": "^1.3.0", - "bn.js": "^4.11.8", - "create-hmac": "^1.1.7", - "elliptic": "^6.4.0", - "nan": "^2.13.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/tiny-secp256k1/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "node_modules/typeforce": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/typeforce/-/typeforce-1.18.0.tgz", - "integrity": "sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g==" - }, - "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/wif": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/wif/-/wif-2.0.6.tgz", - "integrity": "sha512-HIanZn1zmduSF+BQhkE+YXIbEiH0xPr1012QbFEGB0xsKqJii0/SqJjyn8dFv6y36kOznMgMB+LGcbZTJ1xACQ==", - "dependencies": { - "bs58check": "<3.0.0" - } - }, - "node_modules/ws": { - "version": "7.4.6", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", - "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - } - } -} diff --git a/packages/secret-contracts/nunya-contract/node/package.json b/packages/secret-contracts/nunya-contract/node/package.json deleted file mode 100644 index e93bae4..0000000 --- a/packages/secret-contracts/nunya-contract/node/package.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "node", - "type": "module", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [], - "author": "", - "license": "ISC", - "dependencies": { - "@solar-republic/cosmos-grpc": "^0.14.2", - "@solar-republic/neutrino": "^1.0.8", - "dotenv": "^16.4.5", - "ethers": "^5.7.2", - "secretjs": "^1.12.4", - "secure-random": "^1.1.2" - } -} diff --git a/packages/secret-contracts/nunya-contract/node/query_pubkey.js b/packages/secret-contracts/nunya-contract/node/query_pubkey.js deleted file mode 100644 index cc931ea..0000000 --- a/packages/secret-contracts/nunya-contract/node/query_pubkey.js +++ /dev/null @@ -1,19 +0,0 @@ -import { SecretNetworkClient } from "secretjs"; -import dotenv from "dotenv"; -dotenv.config(); - -let query = async () => { - const secretjs = new SecretNetworkClient({ - url: "https://api.pulsar3.scrttestnet.com", - chainId: "pulsar-3", - }); - - const query_tx = await secretjs.query.compute.queryContract({ - contract_address: process.env.SECRET_ADDRESS, - code_hash: process.env.CODE_HASH, - query: { retrieve_pubkey_query: { key: 1 } }, - }); - console.log(query_tx); -}; - -query(); diff --git a/packages/secret-contracts/nunya-contract/node/upload.js b/packages/secret-contracts/nunya-contract/node/upload.js deleted file mode 100644 index 344530f..0000000 --- a/packages/secret-contracts/nunya-contract/node/upload.js +++ /dev/null @@ -1,101 +0,0 @@ -import { SecretNetworkClient, Wallet, coinsFromString } from "secretjs"; -import * as fs from "fs"; -import dotenv from "dotenv"; -dotenv.config(); - -const wallet = new Wallet(process.env.MNEMONIC); - -const contract_wasm = fs.readFileSync("../contract.wasm.gz"); - -const gatewayAddress = "secret10ex7r7c4y704xyu086lf74ymhrqhypayfk7fkj"; - -const gatewayHash = - "012dd8efab9526dec294b6898c812ef6f6ad853e32172788f54ef3c305c1ecc5"; - -const gatewayPublicKey = - "0x046d0aac3ef10e69055e934ca899f508ba516832dc74aa4ed4d741052ed5a568774d99d3bfed641a7935ae73aac8e34938db747c2f0e8b2aa95c25d069a575cc8b"; - -const gatewayPublicKeyBytes = Buffer.from( - gatewayPublicKey.substring(2), - "hex" -).toString("base64"); - -const secretjs = new SecretNetworkClient({ - chainId: "pulsar-3", - url: "https://api.pulsar3.scrttestnet.com", - wallet: wallet, - walletAddress: wallet.address, -}); - -// Declare global variables -let codeId; -let contractCodeHash; -let contractAddress; - -let upload_contract = async () => { - console.log("Starting deployment…"); - - let tx = await secretjs.tx.compute.storeCode( - { - sender: wallet.address, - wasm_byte_code: contract_wasm, - source: "", - builder: "", - }, - { - gasLimit: 4_000_000, - } - ); - - codeId = Number( - tx.arrayLog.find((log) => log.type === "message" && log.key === "code_id") - .value - ); - console.log("codeId: ", codeId); - - contractCodeHash = ( - await secretjs.query.compute.codeHashByCodeId({ code_id: codeId }) - ).code_hash; - console.log(`CODE_HASH: ${contractCodeHash}`); -}; - -let instantiate_contract = async () => { - if (!codeId || !contractCodeHash) { - throw new Error("codeId or contractCodeHash is not set."); - } - console.log("Instantiating contract…"); - - let init = { - gateway_address: gatewayAddress, - gateway_hash: gatewayHash, - gateway_key: gatewayPublicKeyBytes, - }; - let tx = await secretjs.tx.compute.instantiateContract( - { - code_id: codeId, - sender: wallet.address, - code_hash: contractCodeHash, - init_msg: init, - label: "SnakePath Encrypt " + Math.ceil(Math.random() * 10000), - }, - { - gasLimit: 400_000, - } - ); - - //Find the contract_address in the logs - const contractAddress = tx.arrayLog.find( - (log) => log.type === "message" && log.key === "contract_address" - ).value; - - console.log("SECRET_ADDRESS: ", contractAddress); -}; - -// Chain the execution using promises -upload_contract() - .then(() => { - instantiate_contract(); - }) - .catch((error) => { - console.error("Error:", error); - }); diff --git a/packages/secret-contracts/nunya-contract/src/contract.rs b/packages/secret-contracts/nunya-contract/src/contract.rs index 29aee63..2cd31fc 100644 --- a/packages/secret-contracts/nunya-contract/src/contract.rs +++ b/packages/secret-contracts/nunya-contract/src/contract.rs @@ -1,24 +1,27 @@ use crate::{ msg::{ ExecuteMsg, GatewayMsg, InstantiateMsg, QueryMsg, - NewSecretUserStoreMsg, LinkPaymentRefStoreMsg, PayStoreMsg, PayEncryptedWithReceiptStoreMsg, WithdrawToStoreMsg, - ResponseStoreMsg, ResponseRetrievePubkeyMsg, + NewAuthOutStoreMsg, LinkPaymentRefStoreMsg, PayStoreMsg, WithdrawToStoreMsg, + ResponseNewAuthOutStoreMsg, ResponseLinkPaymentRefStoreMsg, ResponsePayStoreMsg, ResponseWithdrawToStoreMsg, ResponseRetrievePubkeyMsg, }, state::{ - NewSecretUser, LinkPaymentRef, Pay, PayEncryptedWithReceipt, WithdrawTo, - State, CONFIG, - PUBKEY_MAP, NEW_SECRET_USER_MAP, LINK_PAYMENT_REF_MAP, PAY_MAP, PAY_ENCRYPTED_WITH_RECEIPT_MAP, WITHDRAW_TO_MAP, + PaymentReceipt, PaymentReferenceBalance, ResponseStatusCode, + State, CONFIG, MY_KEYS, + VIEWING_KEY, VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP, }, }; use cosmwasm_std::{ - entry_point, to_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdError, StdResult, Uint128, Uint256 + entry_point, to_binary, to_vec, coin, Binary, Coin, ContractResult, Deps, DepsMut, Env, MessageInfo, Response, StdError, StdResult, SystemResult, Uint128, Uint256 }; +use secret_toolkit::viewing_key::{ViewingKey, ViewingKeyStore}; use secret_toolkit::utils::{pad_handle_result, pad_query_result, HandleCallback}; use tnls::{ msg::{PostExecutionMsg, PrivContractHandleMsg}, state::Task, }; +use anybuf::Anybuf; + /// pad handle responses and log attributes to blocks of 256 bytes to prevent leaking info based on /// response size pub const BLOCK_SIZE: usize = 256; @@ -30,6 +33,7 @@ pub fn instantiate( _info: MessageInfo, msg: InstantiateMsg, ) -> StdResult { + // Initialise state let state = State { gateway_address: msg.gateway_address, gateway_hash: msg.gateway_hash, @@ -53,67 +57,110 @@ pub fn execute(deps: DepsMut, env: Env, info: MessageInfo, msg: ExecuteMsg) -> S fn try_handle( deps: DepsMut, env: Env, - _info: MessageInfo, + info: MessageInfo, msg: PrivContractHandleMsg, ) -> StdResult { // verify signature with stored gateway public key - let gateway_key = CONFIG.load(deps.storage)?.gateway_key; + let config = CONFIG.load(deps.storage)?; + + // Security + // + // reference: evm-kv-store-demo + if info.sender != config.gateway_address { + return Err(StdError::generic_err( + "Only SecretPath Gateway can call this function", + )); + } + deps.api .secp256k1_verify( msg.input_hash.as_slice(), msg.signature.as_slice(), - gateway_key.as_slice(), + config.gateway_key.as_slice(), ) .map_err(|err| StdError::generic_err(err.to_string()))?; // determine which function to call based on the included handle let handle = msg.handle.as_str(); match handle { - "newSecretUser" => create_new_secret_user(deps, env, msg.input_values, msg.task, msg.input_hash), - "linkPaymentRef" => create_link_payment_ref(deps, env, msg.input_values, msg.task, msg.input_hash), + "newSecretUser" => create_new_auth_out(deps, env, info, msg.input_values, msg.task, msg.input_hash), + "createPaymentReference" => create_payment_reference(deps, env, msg.input_values, msg.task, msg.input_hash), + // handle both `pay` and `payWithReceipt` Solidity function calls using the same `create_pay` Secret contract function "pay" => create_pay(deps, env, msg.input_values, msg.task, msg.input_hash), - "payWithReceipt" => create_pay_encrypted_with_receipt(deps, env, msg.input_values, msg.task, msg.input_hash), + "payWithReceipt" => create_pay(deps, env, msg.input_values, msg.task, msg.input_hash), "withdrawTo" => create_withdraw_to(deps, env, msg.input_values, msg.task, msg.input_hash), _ => Err(StdError::generic_err("invalid handle".to_string())), } } -fn create_new_secret_user( +fn create_new_auth_out( deps: DepsMut, env: Env, + info: MessageInfo, input_values: String, task: Task, input_hash: Binary, ) -> StdResult { let config = CONFIG.load(deps.storage)?; - let input: NewSecretUserStoreMsg = serde_json_wasm::from_str(&input_values) + let input: NewAuthOutStoreMsg = serde_json_wasm::from_str(&input_values) .map_err(|err| StdError::generic_err(err.to_string()))?; - // Parse as u256 - let secret_user = input - .secret_user - .map_err(|err| StdError::generic_err(format!("Invalid _secret: {}", err)))?; + let viewing_key_index = input.secret_user.as_str(); // convert u8 to String - let new_secret_user = NewSecretUser { - secret_user: secret_user + if viewing_key_index.chars().count() == 0 { + return Err(StdError::generic_err("Secret must not be an empty string")); + } + + // https://docs.scrt.network/secret-network-documentation/development/development-concepts/permissioned-viewing/viewing-keys#viewing-keys-implementation + let gateway_account = config.gateway_address.to_owned(); + let mut index_concat: String = gateway_account.to_string(); + let suffix: &str = viewing_key_index; + // mutate in place https://stackoverflow.com/a/30154791/3208553 + index_concat.push_str(suffix); + + // https://docs.scrt.network/secret-network-documentation/development/development-concepts/permissioned-viewing/viewing-keys#viewing-keys-introduction + // https://github.com/scrtlabs/examples/blob/master/secret-viewing-keys/secret-viewing-keys-contract/src/contract.rs + let entropy: &[u8] = b"entropy"; + let viewing_key = ViewingKey::create(deps.storage, &info, &env, gateway_account.as_str(), entropy); + + // Viewing Key + VIEWING_KEY + // TODO - sender is always the gateway contract, or perhaps change this to `info.sender.as_bytes()` + .add_suffix(config.gateway_address.as_bytes()) + .insert(deps.storage, &viewing_key_index.to_string(), &viewing_key)?; + + // Attempt to retrieve existing + let value_payment_reference_to_balances_map: Option> = Some(VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP + .get(deps.storage, &index_concat) + .ok_or_else(|| StdError::generic_err("Value for this VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP key not found"))?); + + // TODO: need to setup viewing key for the mapping, but not necessary to store this example + let init_balance: Coin = coin(0u128, String::new()); + let init_payment_ref = String::new(); + let init_payment_reference_balance = PaymentReferenceBalance { + payment_reference: init_payment_ref, + balance: init_balance, }; - // Extract KeyIter from Result, handle error if necessary - let key_iter_result = NEW_SECRET_USER_MAP.iter_keys(deps.storage); - let mut max_key: u32 = 0; + let mut value_payment_reference_to_balances: Vec = match value_payment_reference_to_balances_map { + Some(payment_reference_to_balances) => payment_reference_to_balances, // If there are existing + None => Vec::new(), // If none are found, start with an empty vector + }; - for key in key_iter_result? { - max_key = max_key.max(key?); - } - let new_key = max_key + 1; + // Add the new to vector + value_payment_reference_to_balances.push(init_payment_reference_balance.clone()); + + // Save updated back to storage + VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP + .insert(deps.storage, &viewing_key, &value_payment_reference_to_balances)?; - // Insert the new item with the new key - NEW_SECRET_USER_MAP.insert(deps.storage, &new_key, &new_secret_user)?; + let response_status_code: ResponseStatusCode = 0u16; - let data = ResponseStoreMsg { - message: true, + let data = ResponseNewAuthOutStoreMsg { + _request_id: task.clone(), + _code: response_status_code, }; let json_string = @@ -121,27 +168,36 @@ fn create_new_secret_user( let result = base64::encode(json_string); + // Get the contract's code hash using the gateway address + let gateway_code_hash = get_contract_code_hash(deps, config.gateway_address.to_string())?; + let callback_msg = GatewayMsg::Output { + // Sepolia network gateway contract Solidity source code + // https://github.com/SecretSaturn/SecretPath/blob/main/TNLS-Gateways/public-gateway/src/Gateway.sol + // Sepolia network gateway contract deployed code (line 383, 914) + // https://sepolia.etherscan.io/address/0x0B6c705db59f7f02832d66B97b03E9EB3c0b4AAB#code + // Secret network gateway contract Rust source code `PostExecutionInfo` + // https://github.com/SecretSaturn/SecretPath/blob/main/TNLS-Gateways/solana-gateway/programs/solana-gateway/src/lib.rs#L737 outputs: PostExecutionMsg { result, - task, + task, // task is the requestId input_hash, }, } .to_cosmos_msg( - config.gateway_hash, + gateway_code_hash, config.gateway_address.to_string(), None, )?; Ok(Response::new() .add_message(callback_msg) - .add_attribute("status", "stored value with key")) + .add_attribute("status", "create_new_auth_out")) } -fn create_link_payment_ref( +fn create_payment_reference( deps: DepsMut, - env: Env, + _env: Env, input_values: String, task: Task, input_hash: Binary, @@ -151,36 +207,69 @@ fn create_link_payment_ref( let input: LinkPaymentRefStoreMsg = serde_json_wasm::from_str(&input_values) .map_err(|err| StdError::generic_err(err.to_string()))?; - // FIXME - // Parse as u256 - let secret_user = input - .secret_user - .map_err(|err| StdError::generic_err(format!("Invalid _secret: {}", err)))?; + let viewing_key_index = input.secret_user.as_str(); // convert u8 to String - let payment_ref = input - .payment_ref - .parse::() - .map_err(|err| StdError::generic_err(format!("Invalid _ref: {}", err)))?; + if viewing_key_index.chars().count() == 0 { + return Err(StdError::generic_err("Secret must not be an empty string")); + } - let link_payment_reference = LinkPaymentRef { - secret_user: secret_user, - payment_ref: payment_ref, - }; + // https://docs.scrt.network/secret-network-documentation/development/development-concepts/permissioned-viewing/viewing-keys#viewing-keys-implementation + let gateway_account = config.gateway_address.to_owned(); + let mut index_concat: String = gateway_account.to_string(); + let suffix: &str = viewing_key_index; + index_concat.push_str(suffix); - // Extract KeyIter from Result, handle error if necessary - let key_iter_result = LINK_PAYMENT_REF_MAP.iter_keys(deps.storage); - let mut max_key: u32 = 0; + let binding = "entropy".to_string(); + let entropy: &str = binding.as_str(); + let result = ViewingKey::check(deps.storage, &index_concat, entropy); + assert_ne!(result, Err(StdError::generic_err("unauthorized"))); - for key in key_iter_result? { - max_key = max_key.max(key?); + let viewing_key = VIEWING_KEY + .get(deps.storage, &index_concat) + .ok_or_else(|| StdError::generic_err("Value for this VIEWING_KEY key not found"))?; + + if viewing_key != index_concat { + return Err(StdError::generic_err("Viewing Key incorrect or not found")); } - let new_key = max_key + 1; - // Insert the item with the new key - LINK_PAYMENT_REF_MAP.insert(deps.storage, &new_key, &link_payment_reference)?; + let payment_ref = input.payment_ref.as_str(); // convert Uint256 to String + + if payment_ref.chars().count() == 0 { + return Err(StdError::generic_err("Payment reference must not be an empty string")); + } + + // TODO: Check stored correctly but move to tests + let value_payment_reference_to_balances_map: Option> = Some(VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP + .get(deps.storage, &index_concat) + .ok_or_else(|| StdError::generic_err("Value for this VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP key not found"))?); + + // TODO: if payment_ref already exists in VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP value then early exit here - let data = ResponseStoreMsg { - message: true, + let new_balance: Coin = coin(0u128, String::new()); + let new_payment_ref = payment_ref; + let new_payment_reference_balance = PaymentReferenceBalance { + payment_reference: new_payment_ref.to_string(), + balance: new_balance, + }; + + let mut value_payment_reference_to_balances: Vec = match value_payment_reference_to_balances_map { + Some(payment_reference_to_balances) => payment_reference_to_balances, // If there are existing + None => Vec::new(), // If none are found, start with an empty vector + }; + + // Add the new to vector + value_payment_reference_to_balances.push(new_payment_reference_balance.clone()); + + // Save updated back to storage + VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP + .insert(deps.storage, &viewing_key, &value_payment_reference_to_balances)?; + + let response_status_code: ResponseStatusCode = 0u16; + + let data = ResponseLinkPaymentRefStoreMsg { + _request_id: task.clone(), + _code: response_status_code, + _reference: new_payment_ref.to_string(), }; let json_string = @@ -188,6 +277,9 @@ fn create_link_payment_ref( let result = base64::encode(json_string); + // Get the contract's code hash using the gateway address + let gateway_code_hash = get_contract_code_hash(deps, config.gateway_address.to_string())?; + let callback_msg = GatewayMsg::Output { outputs: PostExecutionMsg { result, @@ -196,19 +288,19 @@ fn create_link_payment_ref( }, } .to_cosmos_msg( - config.gateway_hash, + gateway_code_hash, config.gateway_address.to_string(), None, )?; Ok(Response::new() .add_message(callback_msg) - .add_attribute("status", "stored value with key")) + .add_attribute("status", "create_payment_reference")) } fn create_pay( deps: DepsMut, - env: Env, + _env: Env, input_values: String, task: Task, input_hash: Binary, @@ -218,110 +310,122 @@ fn create_pay( let input: PayStoreMsg = serde_json_wasm::from_str(&input_values) .map_err(|err| StdError::generic_err(err.to_string()))?; - let payment_ref = input - .payment_ref - .parse::() - .map_err(|err| StdError::generic_err(format!("Invalid _ref: {}", err)))?; + let viewing_key_index = input.secret_user.as_str(); // convert u8 to String + let payment_ref = input.payment_ref.as_str(); // convert Uint256 to String + // TODO: handle error if issue with amount or denomination received + let amount: Uint128 = input.amount.into(); // Uint128 + let denomination = input.denomination.as_str(); + + if viewing_key_index.chars().count() == 0 { + return Err(StdError::generic_err("Secret must not be an empty string")); + } + if payment_ref.chars().count() == 0 { + return Err(StdError::generic_err("Payment reference must not be an empty string")); + } + if amount == >::into(0u128) { + return Err(StdError::generic_err("Payment amount must be greater than 0")); + } + if denomination.chars().count() == 0 { + return Err(StdError::generic_err("Payment denomination must not be an empty string")); + } - // Parse as u256 - let amount = input - .amount - .parse::() - .map_err(|err| StdError::generic_err(format!("Invalid _amount: {}", err)))?; + // https://docs.scrt.network/secret-network-documentation/development/development-concepts/permissioned-viewing/viewing-keys#viewing-keys-implementation + let gateway_account = config.gateway_address.to_owned(); + let mut index_concat: String = gateway_account.to_string(); + let suffix: &str = viewing_key_index; + index_concat.push_str(suffix); - let pay = Pay { - payment_ref: payment_ref, - amount: amount, - }; + let binding = "entropy".to_string(); + let entropy: &str = binding.as_str(); + let result = ViewingKey::check(deps.storage, &index_concat, entropy); + assert_ne!(result, Err(StdError::generic_err("unauthorized"))); - // Extract KeyIter from Result, handle error if necessary - let key_iter_result = PAY_MAP.iter_keys(deps.storage); - let mut max_key: u32 = 0; + let viewing_key = VIEWING_KEY + .get(deps.storage, &index_concat) + .ok_or_else(|| StdError::generic_err("Value for this VIEWING_KEY key not found"))?; - for key in key_iter_result? { - max_key = max_key.max(key?); + if viewing_key != index_concat { + return Err(StdError::generic_err("Viewing Key incorrect or not found")); } - let new_key = max_key + 1; - // Insert the item with the new key - PAY_MAP.insert(deps.storage, &new_key, &pay)?; + // Attempt to retrieve existing + let value_payment_reference_to_balances_map: Option> = Some(VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP + .get(deps.storage, &index_concat) + .ok_or_else(|| StdError::generic_err("Value for this VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP key not found"))?); - let data = ResponseStoreMsg { - message: true, + let mut value_payment_reference_to_balances: Vec = match value_payment_reference_to_balances_map { + Some(payment_reference_to_balances) => payment_reference_to_balances, // If there are existing + None => return Err(StdError::generic_err("No payment references found")), // If none are found, early return }; - let json_string = - serde_json_wasm::to_string(&data).map_err(|err| StdError::generic_err(err.to_string()))?; - - let result = base64::encode(json_string); + // Check if matching `payment_ref` is in the vector since only pay if it exists + let index: Option = Some(value_payment_reference_to_balances.iter().position(|r| r.payment_reference == payment_ref).unwrap()); - let callback_msg = GatewayMsg::Output { - outputs: PostExecutionMsg { - result, - task, - input_hash, + let index_value_payment_reference_to_balances = match index { + Some(val) => { + println!("Found matching payment reference at index: {:#?}", val); + val }, - } - .to_cosmos_msg( - config.gateway_hash, - config.gateway_address.to_string(), - None, - )?; - - Ok(Response::new() - .add_message(callback_msg) - .add_attribute("status", "stored value with key")) -} + None => return Err(StdError::generic_err("No payment references found")), + }; -fn create_pay_encrypted_with_receipt( - deps: DepsMut, - env: Env, - input_values: String, - task: Task, - input_hash: Binary, -) -> StdResult { - let config = CONFIG.load(deps.storage)?; + // Add pay amount to existing balance associated with the payment reference that was found + let new_balance_amount: Uint128 = value_payment_reference_to_balances[index_value_payment_reference_to_balances].balance.amount.saturating_add(amount); + let new_balance: Coin = coin(>::into(new_balance_amount), denomination); - let input: PayEncryptedWithReceiptStoreMsg = serde_json_wasm::from_str(&input_values) - .map_err(|err| StdError::generic_err(err.to_string()))?; - let payment_ref = input - .payment_ref - .parse::() - .map_err(|err| StdError::generic_err(format!("Invalid _ref: {}", err)))?; - - // Parse as u256 - let amount = input - .amount - .parse::() - .map_err(|err| StdError::generic_err(format!("Invalid _amount: {}", err)))?; - - // Parse as u256 - let user_pubkey = input - .user_pubkey - .parse::() - .map_err(|err| StdError::generic_err(format!("Invalid _userPubkey: {}", err)))?; - - let pay_encrypted_with_receipt = PayEncryptedWithReceipt { - payment_ref: payment_ref, - amount: amount, - user_pubkey: user_pubkey + let new_payment_reference_balance = PaymentReferenceBalance { + payment_reference: payment_ref.to_string(), + balance: new_balance, }; - // Extract KeyIter from Result, handle error if necessary - let key_iter_result = PAY_ENCRYPTED_WITH_RECEIPT_MAP.iter_keys(deps.storage); - let mut max_key: u32 = 0; - - for key in key_iter_result? { - max_key = max_key.max(key?); + // Update the index in the vector with the matching payment reference + value_payment_reference_to_balances[index_value_payment_reference_to_balances] = new_payment_reference_balance; + + // Save updated back to storage + VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP + .insert(deps.storage, &viewing_key, &value_payment_reference_to_balances)?; + + let receipt: PaymentReceipt; + + // FIXME: sign receipt using Secret contract's private key, currently just hardcoded. + // But how to get the Secret contract's public and private key? + let signature: Binary = "0x".as_bytes().into(); + + let user_pubkey: Uint256; + if let Some(ref _user_pubkey) = input.user_pubkey { + user_pubkey = *_user_pubkey; + + // TODO: if user_pubkey has been provided then return encrypted receipt and signature with the user_pubkey + // TODO: still need to encrypt below with user_pubkey + receipt = PaymentReceipt { + payment_reference: payment_ref.to_string(), + // TODO: convert Uint256 to Uint128 + // Note: denomination of `Coin` type for the Receipt, since that is handled by the Solidity contract + amount: new_balance_amount.into(), + // TODO: serialise denomination + denomination: denomination.to_string(), + sig: signature, + }; + } else { + // return receipt and signature unencrypted + receipt = PaymentReceipt { + payment_reference: payment_ref.to_string(), + // TODO: convert Uint256 to Uint128 + // Note: denomination of `Coin` type for the Receipt, since that is handled by the Solidity contract + amount: new_balance_amount.into(), + // TODO: serialise denomination + denomination: denomination.to_string(), + sig: signature, + }; } - let new_key = max_key + 1; - // Insert the item with the new key - PAY_ENCRYPTED_WITH_RECEIPT_MAP.insert(deps.storage, &new_key, &pay_encrypted_with_receipt)?; + let response_status_code: ResponseStatusCode = 0u16; - let data = ResponseStoreMsg { - message: true, + let data = ResponsePayStoreMsg { + _request_id: task.clone(), + _code: response_status_code, + _receipt: receipt, }; let json_string = @@ -329,6 +433,9 @@ fn create_pay_encrypted_with_receipt( let result = base64::encode(json_string); + // Get the contract's code hash using the gateway address + let gateway_code_hash = get_contract_code_hash(deps, config.gateway_address.to_string())?; + let callback_msg = GatewayMsg::Output { outputs: PostExecutionMsg { result, @@ -337,19 +444,19 @@ fn create_pay_encrypted_with_receipt( }, } .to_cosmos_msg( - config.gateway_hash, + gateway_code_hash, config.gateway_address.to_string(), None, )?; Ok(Response::new() .add_message(callback_msg) - .add_attribute("status", "stored value with key")) + .add_attribute("status", "create_pay")) } fn create_withdraw_to( deps: DepsMut, - env: Env, + _env: Env, input_values: String, task: Task, input_hash: Binary, @@ -359,40 +466,84 @@ fn create_withdraw_to( let input: WithdrawToStoreMsg = serde_json_wasm::from_str(&input_values) .map_err(|err| StdError::generic_err(err.to_string()))?; - let secret_user = input - .secret_user - .map_err(|err| StdError::generic_err(format!("Invalid _secret: {}", err)))?; + let viewing_key_index = input.secret_user.as_str(); // convert u8 to String + + // Do not include receiving any payment reference since want to ignore it + + // TODO: handle error if issue with amount or denomination received + let amount: Uint128 = input.amount.into(); // Uint128 + let denomination = input.denomination.as_str(); + let withdrawal_address: [u8; 20] = input.withdrawal_address.into(); // or `Addr` + + if viewing_key_index.chars().count() == 0 { + return Err(StdError::generic_err("Secret must not be an empty string")); + } + // Do not validate payment reference since want to ignore it + if amount == >::into(0u128) { + return Err(StdError::generic_err("Payment amount must be greater than 0")); + } + if denomination.chars().count() == 0 { + return Err(StdError::generic_err("Payment denomination must not be an empty string")); + } + // TODO: validate withdrawal address input. check if could be `Addr` type + + // https://docs.scrt.network/secret-network-documentation/development/development-concepts/permissioned-viewing/viewing-keys#viewing-keys-implementation + let gateway_account = config.gateway_address.to_owned(); + let mut index_concat: String = gateway_account.to_string(); + let suffix: &str = viewing_key_index; + index_concat.push_str(suffix); + + let binding = "entropy".to_string(); + let entropy: &str = binding.as_str(); + let result = ViewingKey::check(deps.storage, &index_concat, entropy); + assert_ne!(result, Err(StdError::generic_err("unauthorized"))); - // Parse as u256 - let amount = input - .amount - .parse::() - .map_err(|err| StdError::generic_err(format!("Invalid amount: {}", err)))?; + let value_viewing_key = VIEWING_KEY + .get(deps.storage, &index_concat) + .ok_or_else(|| StdError::generic_err("Value for this VIEWING_KEY key not found"))?; - let withdrawal_address = input - .withdrawal_address - .map_err(|err| StdError::generic_err(format!("Invalid withdrawalAddress: {}", err)))?; + if value_viewing_key != index_concat { + return Err(StdError::generic_err("Viewing Key incorrect or not found")); + } + + // Attempt to retrieve existing + let value_payment_reference_to_balances_map: Option> = Some(VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP + .get(deps.storage, &index_concat) + .ok_or_else(|| StdError::generic_err("Value for this VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP key not found"))?); - let withdrawal_to = WithdrawTo { - secret_user: secret_user, - amount: amount, - withdrawal_address: withdrawal_address + let value_payment_reference_to_balances: Vec = match value_payment_reference_to_balances_map { + Some(payment_reference_to_balances) => payment_reference_to_balances, // If there are existing + None => return Err(StdError::generic_err("No payment references found")), // If none are found, early return }; - // Extract KeyIter from Result, handle error if necessary - let key_iter_result = WITHDRAW_TO_MAP.iter_keys(deps.storage); - let mut max_key: u32 = 0; + // Do not only withdraw associated with a specific payment reference at an index in the storage vector since want to ignore it + // Do not need to check that the `payment_ref` provided exists in storage since ignore it + // Do not need to check using the `payment_ref` that we want to withdraw using: + // the `amount` provided ensuring it is less than or equal to the amount stored associated with the payment reference + // and that the `denomination` matches the provided denomination that we want to withdraw + + // Do not store withdrawal address in state + // Do not transfer anything on Secret Network + // Only authorise the withdrawal + + let mut balance_all_payment_refs: Uint128 = 0u128.into(); + for element in value_payment_reference_to_balances.into_iter() { + if element.balance.denom == denomination { + balance_all_payment_refs += element.balance.amount + } + } - for key in key_iter_result? { - max_key = max_key.max(key?); + if amount > balance_all_payment_refs { + return Err(StdError::generic_err("Withdrawal amount must be less than or equal to total balance of all payment references")); } - let new_key = max_key + 1; - // Insert the item with the new key - WITHDRAW_TO_MAP.insert(deps.storage, &new_key, &withdrawal_to)?; + let response_status_code: ResponseStatusCode = 0u16; - let data = ResponseStoreMsg { - message: true, + let data = ResponseWithdrawToStoreMsg { + _request_id: task.clone(), + _code: response_status_code, + _amount: amount, + _withdrawal_address: withdrawal_address, }; let json_string = @@ -400,6 +551,9 @@ fn create_withdraw_to( let result = base64::encode(json_string); + // Get the contract's code hash using the gateway address + let gateway_code_hash = get_contract_code_hash(deps, config.gateway_address.to_string())?; + let callback_msg = GatewayMsg::Output { outputs: PostExecutionMsg { result, @@ -408,30 +562,87 @@ fn create_withdraw_to( }, } .to_cosmos_msg( - config.gateway_hash, + gateway_code_hash, config.gateway_address.to_string(), None, )?; Ok(Response::new() .add_message(callback_msg) - .add_attribute("status", "stored value with key")) + .add_attribute("status", "DO_THE_WITHDRAWAL")) +} + +// reference: https://github.com/writersblockchain/secretpath-voting/commit/b0b5d8ac7b7d691c7d7ebf0bc52e5aedb8da7e86#diff-a982e501ba4bd05192a8c497bd5093517ea5606f9e341b9b7d09b233068da829R232 +fn get_contract_code_hash(deps: DepsMut, contract_address: String) -> StdResult { + let code_hash_query: cosmwasm_std::QueryRequest = + cosmwasm_std::QueryRequest::Stargate { + path: "/secret.compute.v1beta1.Query/CodeHashByContractAddress".into(), + data: Binary(Anybuf::new().append_string(1, contract_address).into_vec()), + }; + let raw = to_vec(&code_hash_query).map_err(|serialize_err| { + StdError::generic_err(format!("Serializing QueryRequest: {}", serialize_err)) + })?; + let code_hash = match deps.querier.raw_query(&raw) { + SystemResult::Err(system_err) => Err(StdError::generic_err(format!( + "Querier system error: {}", + system_err + ))), + SystemResult::Ok(ContractResult::Err(contract_err)) => Err(StdError::generic_err(format!( + "Querier contract error: {}", + contract_err + ))), + SystemResult::Ok(ContractResult::Ok(value)) => Ok(value), + }?; + // Remove the "\n@" if it exists at the start of the code_hash + let mut code_hash_str = String::from_utf8(code_hash.to_vec()) + .map_err(|err| StdError::generic_err(format!("Invalid UTF-8 sequence: {}", err)))?; + if code_hash_str.starts_with("\n@") { + code_hash_str = code_hash_str.trim_start_matches("\n@").to_string(); + } + Ok(code_hash_str) } #[entry_point] -pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { +pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { let response = match msg { - QueryMsg::RetrievePubkey { key } => retrieve_pubkey_query(deps, key), + QueryMsg::RetrievePubkey {} => to_binary(&retrieve_pubkey_query(deps)?), }; pad_query_result(response, BLOCK_SIZE) } -fn retrieve_pubkey_query(deps: Deps, key: u32) -> StdResult { - let value = PUBKEY_MAP - .get(deps.storage, &key) - .ok_or_else(|| StdError::generic_err("Value not found"))?; - - to_binary(&ResponseRetrievePubkeyMsg { - message: true, +fn retrieve_pubkey_query(deps: Deps) -> StdResult { + let my_keys = MY_KEYS.load(deps.storage)?; + Ok(ResponseRetrievePubkeyMsg { + _key: my_keys.public_key, }) } + +#[cfg(test)] +mod tests { + use super::*; + use cosmwasm_std::testing::{message_info, mock_dependencies, mock_dependencies_with_balances, mock_env}; + use cosmwasm_std::coins; + use cosmwasm_std::{from_binary, StdError}; + + #[test] + fn proper_initialization() { + let mut deps = mock_dependencies(); + // Create some Addr instances for testing + let gateway = deps.api.addr_make("gateway"); + // https://docs.rs/cosmwasm-std/latest/cosmwasm_std/testing/fn.message_info.html + let msg = InstantiateMsg { + gateway_address: gateway.to_string(), + }; + + let info = message_info(&gateway, &coins(1000, "earth")); + // we can just call .unwrap() to assert this was a success + let res = instantiate(deps.as_mut(), mock_env(), info, msg).unwrap(); + + assert_eq!(0, res.messages.len()); + + // it worked, let's query the state + let res = query(deps.as_ref(), mock_env(), QueryMsg::RetrievePubkey {}).unwrap(); + let res: ResponseRetrievePubkeyMsg = from_binary(&res).unwrap(); + assert!(res._key); + } +} diff --git a/packages/secret-contracts/nunya-contract/src/msg.rs b/packages/secret-contracts/nunya-contract/src/msg.rs index 0eec5bc..d4ba81c 100644 --- a/packages/secret-contracts/nunya-contract/src/msg.rs +++ b/packages/secret-contracts/nunya-contract/src/msg.rs @@ -1,10 +1,17 @@ use cosmwasm_std::{Addr, Binary, Uint128, Uint256}; use secret_toolkit::utils::HandleCallback; use tnls::msg::{PostExecutionMsg, PrivContractHandleMsg}; +use tnls::state::{Task}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; +use crate::{ + state::{ + PaymentReceipt, ResponseStatusCode, + } +}; + #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct InstantiateMsg { pub gateway_address: Addr, @@ -19,55 +26,78 @@ pub enum ExecuteMsg { } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct NewSecretUserStoreMsg { - pub secret_user: Addr, +pub struct NewAuthOutStoreMsg { + // TODO - is this key the variable of the parameter provided from Solidity contract to its new_secret_user function? + // secret_user or auth_out + pub secret_user: String, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct LinkPaymentRefStoreMsg { - pub secret_user: Addr, + pub secret_user: String, pub payment_ref: String, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct PayStoreMsg { + pub secret_user: String, pub payment_ref: String, pub amount: Uint128, + pub denomination: String, + pub user_pubkey: Option, // encrypted with receipt } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct PayEncryptedWithReceiptStoreMsg { - pub payment_ref: String, +pub struct WithdrawToStoreMsg { + pub secret_user: String, pub amount: Uint128, - pub user_pubkey: Uint256, + pub denomination: String, + pub withdrawal_address: [u8; 20], } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct WithdrawToStoreMsg { - pub secret_user: Addr, - pub amount: Uint128, - pub withdrawal_address: Addr, +pub struct ResponseNewAuthOutStoreMsg { + pub _request_id: Task, + pub _code: ResponseStatusCode, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct ResponseLinkPaymentRefStoreMsg { + pub _request_id: Task, + pub _code: ResponseStatusCode, + pub _reference: String, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct ResponsePayStoreMsg { + pub _request_id: Task, + pub _code: ResponseStatusCode, + pub _receipt: PaymentReceipt, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct ResponseStoreMsg { - // response message - pub message: bool, +pub struct ResponseWithdrawToStoreMsg { + pub _request_id: Task, + pub _code: ResponseStatusCode, + pub _amount: Uint128, + // TODO: should this be of type `Addr`? does it support EVM addresses? + pub _withdrawal_address: [u8; 20], } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] pub enum QueryMsg { - RetrievePubkey { key: u32 }, + RetrievePubkey {}, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct ResponseRetrievePubkeyMsg { - // response message - pub message: bool, + // TODO: can only access `_requestId` if function called from `try_handle` and callback, but not from queries + // pub _requestId: Uint256, + pub _key: Vec, } -// TODO: this may not be necessary +// TODO: this may not be necessary as not used #[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] pub struct QueryResponse { pub message: String, diff --git a/packages/secret-contracts/nunya-contract/src/state.rs b/packages/secret-contracts/nunya-contract/src/state.rs index 46ec464..d007994 100644 --- a/packages/secret-contracts/nunya-contract/src/state.rs +++ b/packages/secret-contracts/nunya-contract/src/state.rs @@ -1,16 +1,20 @@ -use cosmwasm_std::{Addr, Binary, Uint128, Uint256}; +use cosmwasm_std::{Addr, Binary, Coin, Uint256}; use secret_toolkit::storage::{Item, Keymap}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; +pub static MY_KEYS: Item = Item::new(b"my_keys"); pub static CONFIG: Item = Item::new(b"config"); -pub static PUBKEY_MAP: Keymap> = Keymap::new(b"PUBKEY_MAP"); -pub static NEW_SECRET_USER_MAP: Keymap> = Keymap::new(b"NEW_SECRET_USER_MAP"); -pub static LINK_PAYMENT_REF_MAP: Keymap> = Keymap::new(b"LINK_PAYMENT_REF_MAP"); -pub static PAY_MAP: Keymap> = Keymap::new(b"PAY_MAP"); -pub static PAY_ENCRYPTED_WITH_RECEIPT_MAP: Keymap> = Keymap::new(b"PAY_ENCRYPTED_WITH_RECEIPT_MAP"); -pub static WITHDRAW_TO_MAP: Keymap> = Keymap::new(b"WITHDRAW_TO_MAP"); +pub static VIEWING_KEY: Keymap = Keymap::new(b"VIEWING_KEY"); +pub static VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP: Keymap> = Keymap::new(b"VIEWING_KEY_TO_PAYMENT_REF_TO_BALANCES_MAP"); + +pub type Index = String; +// pub type ContractAddress = [u8; 32]; +pub type ResponseStatusCode = u16; + +// reference: https://github.com/scrtlabs/examples/blob/master/secret-viewing-keys/secret-viewing-keys-contract/src/state.rs +pub type VK = String; // Viewing Key #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct State { @@ -19,33 +23,24 @@ pub struct State { pub gateway_key: Binary, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct NewSecretUser { - pub secret_user: Addr, -} - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct LinkPaymentRef { - pub secret_user: Addr, - pub payment_ref: String, -} - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct Pay { - pub payment_ref: String, - pub amount: Uint128, +// Secret contract keys +// Reference: https://github.com/writersblockchain/aes-encrypt/blob/afa384d69aaddd92b50323fe1b9324f1342a5c0e/src/state.rs#L7 +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] +pub struct MyKeys { + pub public_key: Vec, + pub private_key: Vec, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct PayEncryptedWithReceipt { - pub payment_ref: String, - pub amount: Uint128, - pub user_pubkey: Uint256, +pub struct PaymentReferenceBalance { + pub payment_reference: String, + pub balance: Coin, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -pub struct WithdrawTo { - pub secret_user: Addr, - pub amount: Uint128, - pub withdrawal_address: Addr, +pub struct PaymentReceipt { + pub payment_reference: String, + pub amount: Uint256, + pub denomination: String, + pub sig: Binary, } diff --git a/packages/secret-upload-contract/package.json b/packages/secret-upload-contract/package.json index 8aa0253..3e25b4b 100644 --- a/packages/secret-upload-contract/package.json +++ b/packages/secret-upload-contract/package.json @@ -5,7 +5,7 @@ "private": true, "scripts": { "build": "./node_modules/.bin/tsc --build", - "clean": "./node_modules/.bin/tsc --clean", + "clean": "./node_modules/.bin/tsc --build --clean", "start": "yarn build && node ./dist/index.js" }, "dependencies": { diff --git a/packages/secret-upload-contract/src/index.ts b/packages/secret-upload-contract/src/index.ts index 200ae98..f0416d4 100644 --- a/packages/secret-upload-contract/src/index.ts +++ b/packages/secret-upload-contract/src/index.ts @@ -16,16 +16,29 @@ console.log('wallet: ', wallet); const rootPath = path.resolve(__dirname, '../../../'); // relative to ./dist console.log('rootPath', rootPath) -const contract_wasm: any = fs.readFileSync(`${rootPath}/packages/secret-contracts/nunya-contract/contract.wasm`); +const contract_wasm: any = fs.readFileSync(`${rootPath}/packages/secret-contracts/nunya-contract/contract.wasm.gz`); -const gatewayAddress = "secret10ex7r7c4y704xyu086lf74ymhrqhypayfk7fkj"; +// Secret Testnet +// reference: https://docs.scrt.network/secret-network-documentation/confidential-computing-layer/ethereum-evm-developer-toolkit/supported-networks/secret-gateway/secretpath-testnet-pulsar-3-contracts +// Code ID 3375 +const gatewayAddress = "secret10ex7r7c4y704xyu086lf74ymhrqhypayfk7fkj"; const gatewayHash = - "012dd8efab9526dec294b6898c812ef6f6ad853e32172788f54ef3c305c1ecc5"; - + "ad8ca07ffba1cb26ebf952c29bc4eced8319c171430993e5b5089887f27b3f70"; const gatewayPublicKey = "0x046d0aac3ef10e69055e934ca899f508ba516832dc74aa4ed4d741052ed5a568774d99d3bfed641a7935ae73aac8e34938db747c2f0e8b2aa95c25d069a575cc8b"; +// Secret Mainnet +// reference: https://docs.scrt.network/secret-network-documentation/confidential-computing-layer/ethereum-evm-developer-toolkit/supported-networks/secret-gateway/secretpath-mainnet-secret-4-contracts + +// Code ID 1533 +// const gatewayAddress = "secret1qzk574v8lckjmqdg3r3qf3337pk45m7qd8x02a"; +// const gatewayHash = +// "012dd8efab9526dec294b6898c812ef6f6ad853e32172788f54ef3c305c1ecc5"; +// // TODO: is it correct that the Gateway public key is the same for both Mainnet and Testnet as shown in the docs here, even though they have a different Gateway address? https://docs.scrt.network/secret-network-documentation/confidential-computing-layer/ethereum-evm-developer-toolkit/supported-networks/secret-gateway +// const gatewayPublicKey = +// "0x04a0d632acd0d2f5da02fc385ea30a8deab4d5639d1a821a3a552625ad0f1759d0d2e80ca3adb236d90caf1b12e0ddf3a351c5729b5e00505472dca6fed5c31e2a"; + const gatewayPublicKeyBytes = Buffer.from( gatewayPublicKey.substring(2), "hex" @@ -58,15 +71,20 @@ async function main () { }; type CODE_PARAMS = { - codeId: String | undefined, - contractCodeHash: String | undefined, + codeId: String, + contractCodeHash: String, + }; + + type CONTRACT_PARAMS = { + contractAddress: String, + contractCodeHash: String, }; let upload_contract = async () => { console.log("Starting deployment..."); - let codeId: String | undefined; - let contractCodeHash: String | undefined; + let codeId: String; + let contractCodeHash: String; let tx: any; try { tx = await secretjs.tx.compute.storeCode( @@ -88,12 +106,18 @@ async function main () { tx?.arrayLog?.find((log: any) => log?.type === "message" && log?.key === "code_id")?.value ); + console.log("tx.rawLog: ", tx.rawLog); + console.log("codeId: ", codeId); contractCodeHash = ( await secretjs.query.compute.codeHashByCodeId({ code_id: codeId.toString() }) - ).code_hash; + ).code_hash || ""; console.log(`CODE_HASH: ${contractCodeHash}`); + + if (contractCodeHash == "") { + throw Error("Unable to obtain contractCodeHash"); + } return { codeId, @@ -103,7 +127,11 @@ async function main () { let instantiate_contract = async (params: CODE_PARAMS) => { console.log('params: ', params) - let contractAddress; + if (typeof params.codeId == undefined || typeof params.contractCodeHash == undefined) { + throw Error("Unable to instantiate without codeId and contractCodeHash"); + } + + let contractAddress: String; if (!params.codeId || !params.contractCodeHash) { throw new Error("codeId or contractCodeHash is not set."); @@ -123,7 +151,7 @@ async function main () { sender: wallet.address, code_hash: params.contractCodeHash.toString(), init_msg: initMsg, - label: "Encrypt " + Math.ceil(Math.random() * 10000), + label: "SnakePath Encrypt " + Math.ceil(Math.random() * 10000), }, { gasLimit: 400_000, @@ -131,20 +159,40 @@ async function main () { ); console.log('tx: ', tx) - //Find the contract_address in the logs + // Find the contract_address in the logs contractAddress = tx?.arrayLog?.find( (log) => log?.type === "message" && log?.key === "contract_address" - )?.value; + )?.value || ""; console.log("SECRET_ADDRESS: ", contractAddress); - return contractAddress; + if (contractAddress == "") { + throw Error("Unable to find the contract_address"); + } + + let contractParams = { + contractAddress, + contractCodeHash: params.contractCodeHash, + }; + return contractParams; }; + + let query_pubkey = async (params: CONTRACT_PARAMS) => { + const query_tx = await secretjs.query.compute.queryContract({ + contract_address: params?.contractAddress?.toString(), + code_hash: params?.contractCodeHash?.toString(), + query: { retrieve_pubkey_query: { key: 1 } }, + }); + console.log(query_tx); + } // Chain the execution using promises await upload_contract() .then(async (res) => { - await instantiate_contract(res); + await instantiate_contract(res) + .then(async (contractParams) => { + await query_pubkey(contractParams); + }) }) .catch((error) => { console.error("Error:", error); diff --git a/se-2 readme.md b/se-2 readme.md index b2c1587..90c1e36 100644 --- a/se-2 readme.md +++ b/se-2 readme.md @@ -1,5 +1,4 @@ -# 🏗 Scaffold-ETH 2 - +## Scaffold-ETH 2

Documentation | Website @@ -17,122 +16,6 @@ ![Debug Contracts tab](https://github.com/scaffold-eth/scaffold-eth-2/assets/55535804/b237af0c-5027-4849-a5c1-2e31495cccb1) -## Requirements - -Before you begin, you need to install the following tools: - -- [Node (>= v18.18)](https://nodejs.org/en/download/) -- Yarn ([v1](https://classic.yarnpkg.com/en/docs/install/) or [v2+](https://yarnpkg.com/getting-started/install)) -- [Git](https://git-scm.com/downloads) - -## Quickstart - -To get started with Scaffold-ETH 2, follow the steps below: - -1. Install dependencies if it was skipped in CLI: - -``` -cd my-dapp-example -yarn install -``` - -2. Run a local network in the first terminal: - -``` -yarn chain -``` - -This command starts a local Ethereum network using Hardhat. The network runs on your local machine and can be used for testing and development. You can customize the network configuration in `packages/hardhat/hardhat.config.ts`. - -3. On a second terminal, deploy the test contract: - -``` -yarn deploy -``` - -This command deploys a test smart contract to the local network. The contract is located in `packages/hardhat/contracts` and can be modified to suit your needs. The `yarn deploy` command uses the deploy script located in `packages/hardhat/deploy` to deploy the contract to the network. You can also customize the deploy script. - -4. On a third terminal, start your NextJS app: - -``` -yarn start -``` - -Visit your app on: `http://localhost:3000`. You can interact with your smart contract using the `Debug Contracts` page. You can tweak the app config in `packages/nextjs/scaffold.config.ts`. - -Run smart contract test with `yarn hardhat:test` - -- Edit your smart contract `YourContract.sol` in `packages/hardhat/contracts` -- Edit your frontend homepage at `packages/nextjs/app/page.tsx`. For guidance on [routing](https://nextjs.org/docs/app/building-your-application/routing/defining-routes) and configuring [pages/layouts](https://nextjs.org/docs/app/building-your-application/routing/pages-and-layouts) checkout the Next.js documentation. -- Edit your deployment scripts in `packages/hardhat/deploy` - -### Secret Network - -#### Setup - -* Reference https://docs.scrt.network/secret-network-documentation/development/readme-1 - -* Install Git and Make - https://docs.scrt.network/secret-network-documentation/development/readme-1/setting-up-your-environment#install-requirements - -* Install Rust - ``` - rustup update - rustup default stable - rustup target add wasm32-unknown-unknown - source "$HOME/.cargo/env" - ``` -* Install Cargo Generate - ``` - cargo install cargo-generate --features vendored-openssl - ``` - -* Install dependencies - ``` - nvm use - npm install --global lerna - yarn set version 4.2.2 - corepack enable - corepack prepare yarn@v4.2.2 --activate - ``` - -#### Create, Compile and Deploy Contract (Example: Counter) - -* Reference https://docs.scrt.network/secret-network-documentation/development/readme-1/compile-and-deploy - -``` -mkdir -p packages/secret-contracts && cd packages/secret-contracts -cargo generate --git https://github.com/scrtlabs/secret-template.git --name my-counter-contract -``` - -* Compile. Note: Outputs contract.wasm and contract.wasm.gz file in the root directory of the secret-contracts/my-counter-contract folder - -``` -cd packages/secret-contracts/my-counter-contract -make build -``` - -* FIXME: attempt to fix on macOS hack https://github.com/briansmith/ring/issues/1824 -``` -cd packages/secret-contracts/nunya-contract -/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" -brew install llvm -echo 'export PATH="/opt/homebrew/opt/llvm/bin:$PATH"' >> ~/.zshrc -export LDFLAGS="-L/opt/homebrew/opt/llvm/lib" -export CPPFLAGS="-I/opt/homebrew/opt/llvm/include" -RUSTFLAGS='-C link-arg=-s' cargo build --release --target wasm32-unknown-unknown -make build -``` - -* OPTIONAL - optimize contract code - -* Upload and Instantiate -``` -yarn run secret:clean:uploadContract -yarn run secret:start:uploadContract -``` -* View logs at ./logs/instantiateOutput.log -* View on Secret Testnet block explorer at https://testnet.ping.pub/secret/ - ## Documentation Visit our [docs](https://docs.scaffoldeth.io) to learn how to start building with Scaffold-ETH 2.