Last active
May 18, 2021 22:27
-
-
Save ninegua/bc6bb4ca0e9870ce05042658285dd704 to your computer and use it in GitHub Desktop.
Internet computer ledger utility supporting 2 step transfer (separate sign and send)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type ICPTs = record { | |
e8s : nat64; | |
}; | |
type Duration = record { | |
secs: nat64; | |
nanos: nat32; | |
}; | |
type TimeStamp = record { | |
timestamp_nanos: nat64; | |
}; | |
type ArchiveOptions = record { | |
node_max_memory_size_bytes: opt nat32; | |
max_message_size_bytes: opt nat32; | |
controller_id: principal; | |
}; | |
type BlockHeight = nat64; | |
type Memo = nat64; | |
type AccountIdentifier = text; | |
type SubAccount = vec nat8; | |
type Transfer = variant { | |
Burn: record { | |
from: AccountIdentifier; | |
amount: ICPTs; | |
}; | |
Mint: record { | |
to: AccountIdentifier; | |
amount: ICPTs; | |
}; | |
Send: record { | |
from: AccountIdentifier; | |
to: AccountIdentifier; | |
amount: ICPTs; | |
}; | |
}; | |
type Transaction = record { | |
transfer: Transfer; | |
memo: Memo; | |
created_at: BlockHeight; | |
}; | |
type SendArgs = record { | |
memo: Memo; | |
amount: ICPTs; | |
fee: ICPTs; | |
from_subaccount: opt SubAccount; | |
to: AccountIdentifier; | |
created_at_time: opt TimeStamp; | |
}; | |
type NotifyCanisterArgs = record { | |
block_height: BlockHeight; | |
max_fee: ICPTs; | |
from_subaccount: opt SubAccount; | |
to_canister: principal; | |
to_subaccount: opt SubAccount; | |
}; | |
type AccountBalanceArgs = record { | |
account: AccountIdentifier; | |
}; | |
type LedgerCanisterInitPayload = record { | |
minting_account: AccountIdentifier; | |
initial_values: vec record {AccountIdentifier; ICPTs}; | |
max_message_size_bytes: opt nat32; | |
transaction_window: opt Duration; | |
archive_options: opt ArchiveOptions; | |
send_whitelist: vec record {principal}; | |
} | |
service: (LedgerCanisterInitPayload) -> { | |
send_dfx : (SendArgs) -> (BlockHeight); | |
notify_dfx: (NotifyCanisterArgs) -> (); | |
account_balance_dfx : (AccountBalanceArgs) -> (ICPTs) query; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
set -euo pipefail | |
USAGE="$0 [balance|transfer|sign|send] ... | |
Sub-command: | |
balance <account_id> | |
transfer <amount> <account_id> | |
sign <amount> <account_id> <output_file> | |
send <file> | |
Note that amount must be specified as ICP in decimal, not e8s. | |
" | |
FEE=${FEE:-0.0001} | |
DFX="dfx canister --no-wallet --network=ic" | |
DFX_VERSION=$(dfx --version | sed -e 's/dfx //') | |
test -n "$DFX_VERSION" || (echo "Unable to get dfx version number." && exit 1) | |
test -f "${LEDGER_DID:-}" || (echo "Cannot find ledger.did. Please specify it in the environment variable LEDGER_DID." && exit 1) | |
prepare() { | |
PROJ_DIR=$(mktemp -td dfx-transfer-XXXXXXXX) | |
test -d "$PROJ_DIR" || exit 1 | |
cp "$LEDGER_DID" "$PROJ_DIR/ledger.did" || exit 1 | |
cat >"$PROJ_DIR/dfx.json" <<END | |
{ | |
"version": 1, | |
"dfx": "$DFX_VERSION", | |
"canisters": { | |
"ledger":{ "build": "", "wasm": "", "type": "custom", "candid": "leger.did" } | |
}, | |
"defaults": { "build": { "packtool": "" } }, | |
"networks": {} | |
} | |
END | |
cat >"$PROJ_DIR/canister_ids.json" <<END | |
{ "ledger": { "ic": "ryjl3-tyaaa-aaaaa-aaaba-cai" } } | |
END | |
pushd "$PROJ_DIR" | |
} | |
cleanup() { | |
popd | |
rm -rf "$PROJ_DIR" | |
} | |
get_balance() { | |
prepare | |
local account=${1:-$(dfx ledger account-id)} | |
local result=$($DFX call ledger account_balance_dfx --type idl "(record { account = \"$account\" })") | |
local balance=$(echo "$result"| sed -e 's/.*= \([^ ]*\).*/\1/' -e 's/_//g') | |
printf "%08d" "$balance" | sed -e 's/\(.*\)\(........\)$/\1.\2/' | |
} | |
transfer_args() { | |
local amount=$(printf "%.8f" "$1" | sed -e 's/\.//') | |
local fee=$(printf "%.8f" "$FEE" | sed -e 's/\.//') | |
local account=$2 | |
echo "(record { | |
memo = 0 : nat64; | |
amount = record { e8s = $amount : nat64 }; | |
fee = record { e8s = $fee : nat64 }; | |
to = \"$account\"; | |
created_at_time = record { timestamp_nanos = $(date +%s)000000000 : nat64 } | |
})" | |
} | |
transfer_balance() { | |
local args=$(transfer_args "$1" "$2") | |
prepare | |
$DFX call ledger send_dfx --type idl "$args" | |
cleanup | |
} | |
sign_transfer() { | |
local args=$(transfer_args "$1" "$2") | |
local outfile="$(realpath $3)" | |
prepare | |
$DFX sign ledger send_dfx --file "$outfile" --type idl "$args" | |
cleanup | |
} | |
send_transfer() { | |
local infile="$(realpath $1)" | |
prepare | |
local request_id=$($DFX send "$infile") | |
echo | |
echo "Request ID: $request_id" | |
# Cannot do the following because signer needs to sign rqeuest-status on AG setup first. | |
# $DFX request-status "$request_id" ledger | |
cleanup | |
} | |
case "${1:-}" in | |
"balance") get_balance "${2:-}" ;; | |
"transfer") | |
test "$#" -eq "3" || (echo "$USAGE" && exit 1) | |
transfer_balance "$2" "$3" | |
;; | |
"sign") | |
test "$#" -eq "4" || (echo "$USAGE" && exit 1) | |
sign_transfer "$2" "$3" "$4" | |
;; | |
"send") | |
test "$#" -eq "2" || (echo "$USAGE" && exit 1) | |
send_transfer "$2" | |
;; | |
*) echo "$USAGE" ;; | |
esac |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment