## Example Use Cases - Save `wallet address` as Sam - Send 2 eth to Sam - What is my current wallet holding? - How much eth do I have? - Swap my 100 USDC to ETH - Send 1 eth on 1st of month for next six months to Sam - If eth price falls below $1,700 in next seven days, buy 5 eth ## User Stories - I want to be able to save a wallet address under a name so I can use the name for future interactions - I want to be able to send token/NFTs to a different wallet - I want to be able to swap my assets (eg: USDC to ETH) - I want to be able to make my send and swap transactions recurring/conditional so I don't have to manually do those trasncations over and over again - Conditional will be based on balance or value of asset in a given period of time - I want to be able to view my current wallet holdings like what assets I have, how many and what their current value is in my chosen fiat currency (USD, Euro) so I have clear understanding of my assets - I want to be able to view all the recurring actions I have scheduled so that I can manage them (view, cancel or schedule more) - I want to be able to view all the conditional actions I have scheduled so that I can manage them (view, cancel or schedule more) ## List of wraps to support - Uniswap - approve - swap - Ethers - Converts wei to eth and vice versa - getSignerBalance - getSignerAddress - getGasPrice - signMessage - signTransaction - getChainID - getSignerAddress - getSignerBalance - getGasPrice - estimateEip1559Fees - awaiteTransaction - sendTransaction - sendTransactionAndWait - signMessage - signTransaction - signTypedData - ENS (https://etherscan.io/address/0x283af0b28c62c092c9727f1ee09c02ca627eb7f5#writeContract) - getOwner - checkIfRecordExists - getAddress - getAddressFromDomain - getContentHash - getContentHashFromDomain - getExpiryTime - getNameFromAddress - getTextRecord - registerDomain - reverseRegisterDomain - setName - setAddress - setOwner - setSubdomainOwner - setRecord - setSubdomainRecord - setContentHash - setAddressFromDomain - setContentHashFromDomain - setTextRecord - rentPrice (read) - available (read) - renew (write) - transferOwnership - Safe - createProxy - proxyCreationCode - getNonce - getVersion - approvedHashes - approveHash - getSafeContractNetworks - encodeExecTransaction - deploySafe - predictSafeAddress - getSafeAddress - safeIsDeployed - encodeDeploySafe - getSafeInitializer - createTransaction - createMultiSendTransaction - addSignature - getTransactionHash - signTransactionHash - encodeEnableModuleData - encodeDisableModuleData - encodeMultiSendData - encodeAddOwnerWithThresholdData - encodeRemoveOwnerData - encodeSwapOwnerData - encodeChangeThresholdData - approveTransactionHash - executeTransaction - getOwnersWhoApprovedTx - getSignature - getOwners - getThreshold ## To Train AI * Prompt: I want to save `0x36e0237324b1a52d1d439fd9a0d65fc609008bb4` as Sam - Actions: ```json! [ { "wrap": "adressBook", "method": "setAddress", "args": { "name": "Sam", "address": "0x36e0237324b1a52d1d439fd9a0d65fc609008bb4" } } ] ``` * Prompt: I want to send 2 eth to Sam - Actions: ```json! [ { "wrap": "adressBook", "method": "getAddress", "args": { "name": "Sam" } }, { "wrap": "ethers", "method": "sendTransaction", "args": { "tx": { "to": "$1", "value": "2000000000000000000" } } } ] ``` * Prompt:Can you tell me how much eth I have in `blubberfish.eth`? - Actions: ```json! [ { "wrap": "ens", "method": "getOwner", "args": { "domain": "blubberfish.eth", "registryAddress": "0x..." } }, { "wrap": "ethers", "method": "getBalance", "args": { "address": "$1" } } ] ``` * Prompt: Can you help me swap 100 USDC to eth? - Actions: Ethers: Read how much eth will be given for the selected USDC value + Unisawp: approve + execSawp * Prompt: register `0x36e0237324b1a52d1d439fd9a0d65fc609008bb4` as bluesky.eth - Actions: ```json! [{ wrap: ensWrap, method: "registerDomain", args: { domain: "bluesky.eth", owner: "0x36e0237324b1a52d1d439fd9a0d65fc609008bb4", registrarAddress } }] ``` * Prompt: is `fun.eth` available to buy? - Actions: ```json! [{ wrap: ensWrap, method: "getOwner", args: { domain: "fun.eth", registryAddress } }] ``` -- if owner is null, then is available to buy * Prompt: For how long is `blubberfish.eth` registered? - Actions: ```json! [{ wrap: ensWrap, method: "getExpiryTimes", args: { domain: "blubberfish.eth", registrarAddress: "0x.." } }] ``` * Prompt: I want to renew my registration of `blubberfish.eth` * //TODO Recheck - Actions: ```json! [{ wrap: ensWrap, method: "" }] ``` * Prompt: Tell me all the safes I am in - Actions: Needs API Kit (Which should be developed soon). The endpoint is: `https://safe-transaction-mainnet.safe.global/api/v1/owners/{ADDRESS_OWNER}/safes/` * Prompt: Tell me all the snapshots I follow - Actions: Needs a wrap of this method https://docs.snapshot.org/tools/api#follows * Prompt: Show me all the pending transactions in the safes I am in - Actions: Needs API Kit (Which should be developed soon). The endpoint is: `https://safe-transaction-mainnet.safe.global/api/v1/safes/0xB8ACBe98581A529a1D7EE1e845A331FD0390B251/multisig-transactions/?executed=false` * Prompt: I want to send 200 USDC to John - Actions: - - Look into supported tokens list - - Multiply amount w/decimals - - Pass the new amount ```json! [ { wrap: ethersWrap, method: "callContractMethod", args: { address: USDC_ADDRESS, method: "function transfer(address, uint256)", args: [JOHN_ADDRESS, MULTIPLIED_AMOUNT] } } ] ``` * Prompt: I want to create a new Safe - - Actions: ```json! [ { wrap: safeWrap, method: "deploySafe", args: { input: { safeAccountConfig: { owners: [ADDRESS_OF_USER], threshold: 1 } } } } ] ``` * Prompt: I want to sign "Hello world" with my wallet - - Actions: ```json! [ { wrap: ethersWrap, method: "signMessage", args: { message: "Hello world" } } ] ``` * Prompt: I want to know the gas price - - Actions: ```json! [ { wrap: ethersWrap, method: "getGasPrice" } ] ``` * Prompt: I want to know the address of john.eth - - Actions: ```json! [ { wrap: ensWrap, method: "getOwner", args: { domain: "john.eth". registryAddress: "..." } } ] ``` * Prompt: I want to know the owners of the dorg.eth SAFE - - Actions: ```json! [ { wrap: ensWrap, method: "getOwner", args: { domain: "dorg.eth". registryAddress: "..." } }, { wrap: safeWrap, method: "getOwners", args: { safeAddress: ADDRESS_OF_DORG_ETH } } ] ``` * Prompt: I want to register foo.bar.eth - - Actions: ```json! [ { wrap: ensWrap, method: "registerDomainAndSubdomainsRecursively", args: { domain: "foo.bar.eth", registryAddress: "...", resolverAddress: "...", registrarAddress: "...", owner: USER_ADDRESS, ttl: "0" // TODO: Make sure this works as expected (Probably it should be the amount of time in seconds) } } ] ``` * Prompt: I want to send 400 USD to Jane, and 200 to John * Prompt: I want to know which snapshot spaces am I a member of * Prompt: I want to see which safe transactions I have pending for signature -- Actions: Needs API Kit (Which should be developed soon). The endpoint is: `https://safe-transaction-mainnet.safe.global/api/v1/safes/0xB8ACBe98581A529a1D7EE1e845A331FD0390B251/multisig-transactions/?executed=false` & then need to check confirmations attribute which is an array that has `owner` attribute; all the transactions that doesn't have the logged in wallet in its array should appear * Prompt: I want to know which open proposals I should see on Snapshot * Prompt: I want to see what are the voting options, results and comments from the proposal with description "Invest in apple" * Prompt: I want to create a proposal in snapshot that has * Prompt: I want to add a signer to my safe * Prompt: I want to send 200 usdc to jhon.eth * Prompt: I want to see my wallet balances in usd * Prompt: I want to see all pending transactions from my safe * Prompt: I want to propose a transaction to my safe * Prompt: I want to execute an already signed transaction * Prompt: I want to see what does the transaction number 46 from my safe does * Prompt: I want to fetch the file Qm... from IPFS <!-- * Prompt: I want to upload a file to IPFS --> * Prompt: I want to upload the image from this link URL_TO_IMAGE to opensea and sell it for 200 usdc * Prompt: I want to convert 300 USDC from ethereum to arbitrum ## MVP: Must-haves - Gallery with actions and workflows - Recurrent/conditional workflows - Being able to create your own workflows with or without AI - AI that helps you understand you intention and saves you time - Being able to save workflows as if we were talking about a dune dashboard. - Take a look here to dune or flipside - Save as much data as possible from intentations. - We are using prompting to boostrap the idea, but we are gonna end up needing to fine tune a model with this data. This a new task we need to teach the model. - Use cases: - System actions: Address book (save, retrieve contacts) - Ethereum wrap: Full ethereum wallet functionality (send, receive, save contacts, ENS names as first class citizens, historical data) - Uniswap wrap: Swapping - Multi-send - On-ramping/Off-ramping (We can use 3rd party api) - User analytics ## MVP: Nice-to-haves - Use the result of a previous action as input of the following - Use cases: - Cross-chain bridging - Account abstraction for gas payment in ERC20 ## Future goals - Recommendation system for each user ## Open questions - What's the main primitive? Workflows or actions? - How do we achieve recurring actions? - Can system actions be wraps? Should they? - How's compatibility handled between action blocks? Not all action blocks are compatible with each other. For example: sending ETH -> creating a SAFE. It doesn't make sense to use the output of the first action as the input of the following. -------------- ## Decisions - AI model training: don't have the AI model understand Polywrap or its underlying mechanisms. The AI should only understand high level actions and their inputs. -------------- Future Fine-tuning examples: - input: send eth - Output modelo: [eth_send, {}] - I want to sent eth to fabian.eth - Output: [eth_send, {to:fabian.eth}] - I want to sent eth to fabian.eth each week - Output: [(eth_send, {to:fabian.eth, recurrent: 1}), ] - input: send 9 eth - Output: [eth_send, {value: 9}] --- ## User flows ### Case 1: Manual Workflow building 1. User starts workflow builder 2. Workflow gets created in the backend with an autogenerated ID, to be retrieved later. Each user action on the workflow re-saves workflow state in the backend 3. User selects action blocks 4. User fills inputs for each block 5. User hits executes 6. User gets prompted to give the workflow a name and description (maybe make it public?). Incentivize people to give workflows names and useful descriptions ### Case 2: Intention based Workflow building 1. User types intention in input box 2. The backend saves the user intention + the AI response 3. The backend creates a workflow based on the AI response with an autogenerated ID and returns it to the app. Process continues from Case 1's step 3