[[module]] name = "sol" derivation_prefix = "m/44'/501'/0'" algorithm = "Ed25519" [[module.workflow]] # The name of the workflow, which can be called by: # `icepick workflow sol transfer-token` name = "transfer-token" # These values are used as inputs for other workflows, acquired from the CLI. # These values can only be strings, but other values can be any value that can # be serialized by serde_json::Value. # These values can also be loaded using "internal-load-file", using some form # of later-defined signature validation. inputs = ["from_address", "to_address", "token_name", "token_amount"] # Get the token address and token decimals for the given token [[module.workflow.step]] type = "sol-get-token-info" # The key is the key that is passed to the program in the # `values` field. The value is the item in storage. In this case, # we read a `token-name` from our input, but the operation expects `token`. inputs = { token = "token_name" } # Because these two fields are currently unused in our storage, we can grab # them from the outputs of our module. The key is the key of the output value # we want to store, and the value is the name to be assigned in storage. outputs = { token_address = "token_address", token_decimals = "token_decimals" } # Load the transaction nonce from the SD card [[module.workflow.step]] type = "internal-load-file" # Pre-defined values to be passed to the module. # In this case, the `filename` field is reserved for marking which file to load. values = { filename = "nonce.json" } # This value is marked to be saved in-memory, and can be used as an input for # later steps. outputs = { nonce_authority = "nonce_authority", nonce_data = "nonce_data", nonce_address = "nonce_address" } [[module.workflow.step]] # Generate an unsigned Transaction # This step MUST run immediately before sol-sign, as in the current version of # Icepick, keys are only held in memory in-between a single module invocation. type = "sol-transfer-token" # If using a lot of inputs, it may be best to use a non-inline table. # Non-inline tables _must_ be the last step, as otherwise, `outputs` for # example would be considered a member of `inputs`. In this case, we use a # non-inline table for `outputs` even though it would fit on one line, to avoid # the ambiguity. [module.workflow.step.inputs] amount = "token_amount" token_address = "token_address" decimals = "token_decimals" to_address = "to_address" from_address = "from_address" [module.workflow.step.outputs] instructions = "instructions" derivation_accounts = "derivation_accounts" [[module.workflow.step]] type = "sol-compile" [module.workflow.step.inputs] instructions = "instructions" derivation_accounts = "derivation_accounts" nonce_address = "nonce_address" nonce_authority = "nonce_authority" nonce_data = "nonce_data" [module.workflow.step.outputs] transaction = "unsigned_transaction" # Sign the transaction [[module.workflow.step]] type = "sol-sign" [module.workflow.step.inputs] transaction = "unsigned_transaction" blockhash = "nonce_data" [module.workflow.step.outputs] transaction = "signed_transaction" # Write the signed transaction to a file [[module.workflow.step]] type = "internal-save-file" # We are using a static filename here, so we use `values` instead of `inputs`. values = { filename = "transaction.json" } # All fields in both `inputs` and `values`, other than `filename`, will be # persisted to the file. In this case, the `transaction` field of the file will # contain the signed transaction. inputs = { transaction = "signed_transaction" } # NOTE: To get a nonce address, the `generate-nonce-account` workflow should be # run. It is the only workflow that uses a blockhash, which is why a # `broadcast-with-blockhash` or similar is not, and should not be, implemented. [[module.workflow]] name = "broadcast" inputs = ["nonce_address", "cluster"] [[module.workflow.step]] type = "sol-get-nonce-account-data" inputs = { nonce_address = "nonce_address", cluster = "cluster" } outputs = { authority = "nonce_authority", durable_nonce = "nonce" } [[module.workflow.step]] type = "internal-save-file" values = { filename = "nonce.json" } inputs = { nonce_authority = "nonce_authority", nonce_data = "nonce", nonce_address = "nonce_address" } [[module.workflow.step]] type = "internal-load-file" values = { filename = "transaction.json" } outputs = { transaction = "transaction" } [[module.workflow.step]] type = "sol-broadcast" inputs = { cluster = "cluster", transaction = "transaction" } outputs = { status = "status", url = "url", error = "error" } [[module.workflow]] name = "generate-nonce-account" inputs = ["cluster", "authorization_address"] [[module.workflow.step]] type = "sol-generate-wallet" [[module.workflow.step]] type = "sol-get-wallet-address" outputs = { pubkey = "wallet_pubkey" } [[module.workflow.step]] type = "sol-await-funds" inputs = { address = "wallet_pubkey", cluster = "cluster" } # enough to cover two signatures and the 1_500_000 approx. rent fee values = { lamports = "1510000" } [[module.workflow.step]] type = "sol-get-blockhash" inputs = { cluster = "cluster" } outputs = { blockhash = "blockhash" } [[module.workflow.step]] type = "sol-create-nonce-account-and-signing-key" [module.workflow.step.inputs] from_address = "wallet_pubkey" authorization_address = "authorization_address" [module.workflow.step.outputs] transaction = "unsigned_transaction" nonce_pubkey = "nonce_pubkey" nonce_privkey = "private_keys" [[module.workflow.step]] type = "sol-sign" [module.workflow.step.inputs] blockhash = "blockhash" signing_keys = "private_keys" transaction = "unsigned_transaction" [module.workflow.step.outputs] transaction = "signed_transaction" [[module.workflow.step]] type = "sol-broadcast" inputs = { cluster = "cluster", transaction = "signed_transaction" } outputs = { status = "status", url = "url" } [[module.workflow.step]] type = "internal-cat" inputs = { status = "status", url = "url", nonce_account = "nonce_pubkey" } outputs = { status = "status", url = "url", nonce_account = "nonce_account" } [[module.workflow]] # Transfer SOL from one address to another. name = "transfer" inputs = ["to_address", "from_address", "amount"] [[module.workflow.step]] type = "internal-load-file" values = { filename = "nonce.json" } outputs = { nonce_authority = "nonce_authority", nonce_data = "nonce_data", nonce_address = "nonce_address" } [[module.workflow.step]] type = "sol-transfer" inputs = { from_address = "from_address", to_address = "to_address", amount = "amount" } outputs = { instructions = "instructions", derivation_accounts = "derivation_accounts" } [[module.workflow.step]] type = "sol-compile" [module.workflow.step.inputs] instructions = "instructions" derivation_accounts = "derivation_accounts" nonce_address = "nonce_address" nonce_authority = "nonce_authority" nonce_data = "nonce_data" [module.workflow.step.outputs] transaction = "unsigned_transaction" [[module.workflow.step]] type = "sol-sign" inputs = { blockhash = "nonce_data", transaction = "unsigned_transaction" } outputs = { transaction = "signed_transaction" } [[module.workflow.step]] type = "internal-save-file" values = { filename = "transaction.json" } inputs = { transaction = "signed_transaction" }