Skip to content

Instantly share code, notes, and snippets.

@atengberg
Last active February 14, 2023 21:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save atengberg/689ebd6ca309baf51d775f98a9e56f70 to your computer and use it in GitHub Desktop.
Save atengberg/689ebd6ca309baf51d775f98a9e56f70 to your computer and use it in GitHub Desktop.
comment level verbosity
Example A (**verbose in-method-body comments**)
public shared ({ caller }) func verify_invoice(
{ id } : Types.VerifyInvoiceArgs,
) : async Types.VerifyInvoiceResult {
switch (getInvoiceIfAuthorized(invoices.get(id), caller, #Verify)) {
// Caller is not authorized or invoice not found.
case (#err err) return #err(err);
// Caller is creator or on invoice's verify permissions list.
case (#ok invoice) {
if (Option.isSome(invoice.verifiedPaidAtTime)) {
return #ok(#VerifiedAlready({ invoice = toCallerExpectedInvoice(invoice) }));
};
// Check the invoice isn't already being verified or having balance recovered.
if (isAlreadingProcessing(id, caller)) {
return #err({ kind = #InProgress });
};
// Lock-in the invoice while being processed.
isAlreadyProcessingLookup.put(id, (Time.now(), caller));
// Get the invoice's subaccount to query its balance.
let invoiceSubaccountAddress = SupportedToken.getInvoiceSubaccountAddress({
token;
id;
creator;
canisterId = getInvoiceCanisterId_();
});
// Call the corresponding ledger's balance service method.
let currentInvoiceBalance : Result.Result<Nat, Text> = try {
switch invoiceSubaccountAddress {
case (#ICP accountIdentifier) {
let { e8s } = await Ledger_ICP.account_balance({
account = accountIdentifier;
});
#ok(Nat64.toNat(e8s));
};
case (#ICP_nns accountIdentifier) {
let { e8s } = await Ledger_ICP_NNS.account_balance({
account = accountIdentifier;
});
#ok(Nat64.toNat(e8s));
};
case (#ICRC1_ExampleToken account) #ok(await Ledger_ICRC1_Ex1.icrc1_balance_of(account));
case (#ICRC1_ExampleToken2 account) #ok(await Ledger_ICRC1_Ex2.icrc1_balance_of(account));
};
} catch e {
#err("Balance call trapped:\n" # Error.message(e));
};
switch currentInvoiceBalance {
case (#err err) {
// Unlock and return the caught & trapped intercanister call.
isAlreadyProcessingLookup.delete(id);
return #err({ kind = #CaughtException(err) });
};
case (#ok bal) {
if (bal < invoice.amountDue) {
// Balance is less than the amount due.
if (bal > 0) {
// Some payment was made, format amount to token type.
let partialAmountPaid = SupportedTokenTypes.toTokenAmount(invoice.token, bal);
// Unlock and return the partial amount paid to the caller.
isAlreadyProcessingLookup.delete(id);
// Rest of method
....
Or Example B
public shared ({ caller }) func verify_invoice(
{ id } : Types.VerifyInvoiceArgs,
) : async Types.VerifyInvoiceResult {
switch (getInvoiceIfAuthorized_(invoices_.get(id), caller, #Verify)) {
case (#err err) return #err(err);
case (#ok invoice) {
let { token; creator } = invoice;
if (Option.isSome(invoice.verifiedPaidAtTime)) {
return #ok(#VerifiedAlready({ invoice = toCallerExpectedInvoice_(invoice) }));
};
if (isAlreadingProcessing_(id, caller)) {
return #err({ kind = #InProgress });
};
isAlreadyProcessingLookup_.put(id, (Time.now(), caller));
// Get the invoice's subaccount to query its balance.
let invoiceSubaccountAddress = SupportedToken.getInvoiceSubaccountAddress({
token;
id;
creator;
canisterId = getInvoiceCanisterId_();
});
let currentInvoiceBalance : Result.Result<Nat, Text> = try {
switch invoiceSubaccountAddress {
case (#ICP accountIdentifier) {
let { e8s } = await Ledger_ICP.account_balance({
account = accountIdentifier;
});
#ok(Nat64.toNat(e8s));
};
case (#ICP_nns accountIdentifier) {
let { e8s } = await Ledger_ICP_nns.account_balance({
account = accountIdentifier;
});
#ok(Nat64.toNat(e8s));
};
case (#ICRC1_ExampleToken account) #ok(await Ledger_ICRC1_Ex1.icrc1_balance_of(account));
case (#ICRC1_ExampleToken2 account) #ok(await Ledger_ICRC1_Ex2.icrc1_balance_of(account));
};
} catch e {
// If the inter-canister call failed.
#err("Balance call trapped:\n" # Error.message(e));
};
switch currentInvoiceBalance {
case (#err err) {
isAlreadyProcessingLookup_.delete(id);
return #err({ kind = #CaughtException(err) });
};
case (#ok bal) {
if (bal < invoice.amountDue) {
if (bal > 0) {
let partialAmountPaid = SupportedToken.wrapAsTokenAmount(token, bal);
isAlreadyProcessingLookup_.delete(id);
/// rest of method
In either case this is the Motokodoc header:
/****Verifies payment of an invoice for a given invoice id.**
An invoice is verified paid if the balance of its payment address ("invoice subaccount") equals
or exceeds the amount due for that invoice. If an invoice is verified as paid the total amount of
balance in that invoice's subaccount is transferred to the principal subaccount address of that
invoice's creator (less the cost of that token type's transfer fee). Additionally the invoice's
hashmap record is updated to include the time of verification and returned to the caller. If no
payment has been made the invoice will not be verified and this will return `#Unpaid`; if there's
only been partial payment the invoice will also not be verified and this will return `#IncompletePayment`
with the `partialAmountPaid`. If this is called after an invoice has already been verified, it will
return the invoice as `#VerifiedAlready`.
The process of verifying invoices is synchronized by locking to the invoice's id to prevent overwriting
in the event multiple callers try to verify the same invoice (or call for balance recovery at the same time);
however this lock will automatically be released if enough time has elapsed between calls.
_Only authorized for the invoice's creator and those on the invoice's verify permission list._ */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment