Skip to content

Commit

Permalink
Fix parallelization - inline async functions, refactor internals to m…
Browse files Browse the repository at this point in the history
…ock the icrc2 actor instead of the function.
  • Loading branch information
ByronBecker committed Sep 12, 2024
1 parent 9d43b1b commit ce9c070
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 123 deletions.
30 changes: 15 additions & 15 deletions internal/WrappedICRC2Actor.mo → internal/ICRCCall.mo
Original file line number Diff line number Diff line change
Expand Up @@ -26,29 +26,29 @@ module {
icrc2Actor : ICRC2Interface.ICRC2Actor,
passedBatchSize: Nat,
allowances: [ICRC2Interface.AllowanceArgs],
allowanceFunction : (ICRC2Interface.ICRC2Actor, ICRC2Interface.AllowanceArgs) -> async* ICRC2Interface.Allowance
//allowanceFunction : (ICRC2Interface.ICRC2Actor, ICRC2Interface.AllowanceArgs) -> async* ICRC2Interface.Allowance
) : async* [ICRC2Interface.Allowance] {
let batchSize = if (passedBatchSize > BATCH_SIZE_LIMIT) {
print("You passed in a batch size of " # debug_show(passedBatchSize) # ", but the current max batch size is " # debug_show(BATCH_SIZE_LIMIT) # ". Defaulting to a batch size of " # debug_show(BATCH_SIZE_LIMIT) # ".");
BATCH_SIZE_LIMIT;
} else { passedBatchSize };
let allowanceFutures = Buffer.Buffer<async* ICRC2Interface.Allowance>(batchSize);
let allowanceFutures = Buffer.Buffer<async ICRC2Interface.Allowance>(batchSize);
let allowanceResults = Buffer.Buffer<ICRC2Interface.Allowance>(allowances.size());

for (allowanceArgs in allowances.vals()) {
print("allowanceArgs: " # debug_show(allowanceArgs));
allowanceFutures.add(allowanceFunction(icrc2Actor, allowanceArgs));
allowanceFutures.add(icrc2Actor.icrc2_allowance(allowanceArgs));
if (allowanceFutures.size() >= batchSize) {
for (allowanceFuture in allowanceFutures.vals()) {
allowanceResults.add(await* allowanceFuture);
allowanceResults.add(await allowanceFuture);
};
allowanceFutures.clear();
};
};

// Add any remaining results
for (allowanceFuture in allowanceFutures.vals()) {
allowanceResults.add(await* allowanceFuture);
allowanceResults.add(await allowanceFuture);
};

Buffer.toArray(allowanceResults);
Expand All @@ -59,28 +59,28 @@ module {
icrc2Actor : ICRC2Interface.ICRC2Actor,
passedBatchSize: Nat,
approvals: [ICRC2Interface.ApproveArgs],
approveFunction : (ICRC2Interface.ICRC2Actor, ICRC2Interface.ApproveArgs) -> async* { #Ok : Nat; #Err : ICRC2Interface.ApproveError }
//approveFunction : (ICRC2Interface.ICRC2Actor, ICRC2Interface.ApproveArgs) -> async* { #Ok : Nat; #Err : ICRC2Interface.ApproveError }
) : async* [{ #Ok : Nat; #Err : ICRC2Interface.ApproveError }] {
let batchSize = if (passedBatchSize > BATCH_SIZE_LIMIT) {
print("You passed in a batch size of " # debug_show(passedBatchSize) # ", but the current max batch size is " # debug_show(BATCH_SIZE_LIMIT) # ". Defaulting to a batch size of " # debug_show(BATCH_SIZE_LIMIT) # ".");
BATCH_SIZE_LIMIT;
} else { passedBatchSize };
let approvalFutures = Buffer.Buffer<async* { #Ok : Nat; #Err : ICRC2Interface.ApproveError }>(batchSize);
let approvalFutures = Buffer.Buffer<async { #Ok : Nat; #Err : ICRC2Interface.ApproveError }>(batchSize);
let approvalResults = Buffer.Buffer<{ #Ok : Nat; #Err : ICRC2Interface.ApproveError }>(approvals.size());

for (approvalArgs in approvals.vals()) {
approvalFutures.add(approveFunction(icrc2Actor, approvalArgs));
approvalFutures.add(icrc2Actor.icrc2_approve(approvalArgs));
if (approvalFutures.size() >= batchSize) {
for (approvalFuture in approvalFutures.vals()) {
approvalResults.add(await* approvalFuture);
approvalResults.add(await approvalFuture);
};
approvalFutures.clear();
};
};

// Add any remaining results
for (approvalFuture in approvalFutures.vals()) {
approvalResults.add(await* approvalFuture);
approvalResults.add(await approvalFuture);
};

Buffer.toArray(approvalResults);
Expand All @@ -92,28 +92,28 @@ module {
icrc2Actor : ICRC2Interface.ICRC2Actor,
passedBatchSize : Nat,
transfers: [ICRC2Interface.TransferFromArgs],
transferFunction : (ICRC2Interface.ICRC2Actor, ICRC2Interface.TransferFromArgs) -> async* { #Ok : Nat; #Err : ICRC2Interface.TransferFromError }
//transferFunction : (ICRC2Interface.ICRC2Actor, ICRC2Interface.TransferFromArgs) -> async* { #Ok : Nat; #Err : ICRC2Interface.TransferFromError }
) : async* [{ #Ok : Nat; #Err : ICRC2Interface.TransferFromError }] {
let batchSize = if (passedBatchSize > BATCH_SIZE_LIMIT) {
print("You passed in a batch size of " # debug_show(passedBatchSize) # ", but the current max batch size is " # debug_show(BATCH_SIZE_LIMIT) # ". Defaulting to a batch size of " # debug_show(BATCH_SIZE_LIMIT) # ".");
BATCH_SIZE_LIMIT;
} else { passedBatchSize };
let transferFutures = Buffer.Buffer<async* { #Ok : Nat; #Err : ICRC2Interface.TransferFromError }>(batchSize);
let transferFutures = Buffer.Buffer<async { #Ok : Nat; #Err : ICRC2Interface.TransferFromError }>(batchSize);
let transferResults = Buffer.Buffer<{ #Ok : Nat; #Err : ICRC2Interface.TransferFromError }>(transfers.size());

for (transferArgs in transfers.vals()) {
transferFutures.add(transferFunction(icrc2Actor, transferArgs));
transferFutures.add(icrc2Actor.icrc2_transfer_from(transferArgs));
if (transferFutures.size() >= batchSize) {
for (transferFuture in transferFutures.vals()) {
transferResults.add(await* transferFuture);
transferResults.add(await transferFuture);
};
transferFutures.clear();
};
};

// Add any remaining results
for (transferFuture in transferFutures.vals()) {
transferResults.add(await* transferFuture);
transferResults.add(await transferFuture);
};

Buffer.toArray(transferResults);
Expand Down
2 changes: 1 addition & 1 deletion mops.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "icrc2-batch"
version = "1.0.0"
version = "1.0.1"
description = "Batch functionality for ICRC-2 enabled token ledgers"
repository = "https://github.com/MemeFighterCo/icrc2-batch"
keywords = [ "ICRC", "ICRC-2", "transaction", "token", "ledger" ]
Expand Down
17 changes: 7 additions & 10 deletions src/ICRC2Actor.mo
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Principal "mo:base/Principal";
import ICRC2Interface "ICRC2Interface";
import Buffer "mo:base/Buffer";
import { print } "mo:base/Debug";
import WrappedIcrc2Actor "../internal/WrappedICRC2Actor";
import ICRCCall "../internal/ICRCCall";
import { BATCH_SIZE_LIMIT } "../internal/Constants";

module {
Expand Down Expand Up @@ -38,49 +38,46 @@ module {

/// Get the allowance for a spender on an account
public func icrc2_allowance(args: ICRC2Interface.AllowanceArgs) : async* ICRC2Interface.Allowance {
await* WrappedIcrc2Actor.icrc2_allowance(icrc2Actor, args);
await* ICRCCall.icrc2_allowance(icrc2Actor, args);
};

/// Approve a spender to spend a certain amount on behalf of the owner
public func icrc2_approve(args: ICRC2Interface.ApproveArgs) : async* { #Ok : Nat; #Err : ICRC2Interface.ApproveError } {
await* WrappedIcrc2Actor.icrc2_approve(icrc2Actor, args);
await* ICRCCall.icrc2_approve(icrc2Actor, args);
};

/// Transfer an approved amount from one account to another
public func icrc2_transfer_from(args: ICRC2Interface.TransferFromArgs) : async* { #Ok : Nat; #Err : ICRC2Interface.TransferFromError } {
await* WrappedIcrc2Actor.icrc2_transfer_from(icrc2Actor, args);
await* ICRCCall.icrc2_transfer_from(icrc2Actor, args);
};

/// Batch get allowances provided a list of allowance arguments
/// Note: If one call fails, the entire batch will fail
public func icrc2_allowance_batch(allowances: [ICRC2Interface.AllowanceArgs]) : async* [ICRC2Interface.Allowance] {
await* WrappedIcrc2Actor.wrapped_icrc2_allowance_batch(
await* ICRCCall.wrapped_icrc2_allowance_batch(
icrc2Actor,
limitedBatchSize,
allowances,
WrappedIcrc2Actor.icrc2_allowance
);
};

/// Batch approval provided a list of approval arguments
/// Note: If one call traps, the entire batch will fail (expected errors handled gracefully by the variant type)
public func icrc2_approve_batch(approvals: [ICRC2Interface.ApproveArgs]) : async* [{ #Ok : Nat; #Err : ICRC2Interface.ApproveError }] {
await* WrappedIcrc2Actor.wrapped_icrc2_approve_batch(
await* ICRCCall.wrapped_icrc2_approve_batch(
icrc2Actor,
limitedBatchSize,
approvals,
WrappedIcrc2Actor.icrc2_approve
);
};

/// Batch transfer_from provided a list of transfer_from arguments
/// Note: If one call traps, the entire batch will fail (expected errors handled gracefully by the variant type)
public func icrc2_transfer_from_batch(transfers: [ICRC2Interface.TransferFromArgs]) : async* [{ #Ok : Nat; #Err : ICRC2Interface.TransferFromError }] {
await* WrappedIcrc2Actor.wrapped_icrc2_transfer_from_batch(
await* ICRCCall.wrapped_icrc2_transfer_from_batch(
icrc2Actor,
limitedBatchSize,
transfers,
WrappedIcrc2Actor.icrc2_transfer_from
);
};
};
Expand Down
17 changes: 7 additions & 10 deletions src/lib.mo
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
import ICRC2Actor "ICRC2Actor";
import ICRC2Interface "ICRC2Interface";
import WrappedIcrc2Actor "../internal/WrappedICRC2Actor";
import ICRCCall "../internal/ICRCCall";

module {
/// Class capable of batching ICRC2 transactions to ICRC2 actor canisters
public let ICRC2BatchActor = ICRC2Actor.ICRC2BatchActor;

/// Get the allowance for a spender on an account
public func icrc2_allowance(icrc2Actor: ICRC2Interface.ICRC2Actor, args: ICRC2Interface.AllowanceArgs) : async* ICRC2Interface.Allowance {
return await* WrappedIcrc2Actor.icrc2_allowance(icrc2Actor, args);
return await* ICRCCall.icrc2_allowance(icrc2Actor, args);
};

/// Approve a spender to spend a certain amount on behalf of the owner
public func icrc2_approve(icrc2Actor: ICRC2Interface.ICRC2Actor, args: ICRC2Interface.ApproveArgs) : async* { #Ok : Nat; #Err : ICRC2Interface.ApproveError } {
return await* WrappedIcrc2Actor.icrc2_approve(icrc2Actor, args);
return await* ICRCCall.icrc2_approve(icrc2Actor, args);
};

/// Transfer an approved amount from one account to another
public func icrc2_transfer_from(icrc2Actor: ICRC2Interface.ICRC2Actor, args: ICRC2Interface.TransferFromArgs) : async* { #Ok : Nat; #Err : ICRC2Interface.TransferFromError } {
return await* WrappedIcrc2Actor.icrc2_transfer_from(icrc2Actor, args);
return await* ICRCCall.icrc2_transfer_from(icrc2Actor, args);
};

/// Batch get allowances provided a list of allowance arguments
Expand All @@ -28,11 +28,10 @@ module {
batchSize: Nat,
allowances: [ICRC2Interface.AllowanceArgs]
) : async* [ICRC2Interface.Allowance] {
return await* WrappedIcrc2Actor.wrapped_icrc2_allowance_batch(
return await* ICRCCall.wrapped_icrc2_allowance_batch(
icrc2Actor,
batchSize,
allowances,
WrappedIcrc2Actor.icrc2_allowance
);
};

Expand All @@ -43,11 +42,10 @@ module {
batchSize: Nat,
approvals: [ICRC2Interface.ApproveArgs]
) : async* [{ #Ok : Nat; #Err : ICRC2Interface.ApproveError }] {
return await* WrappedIcrc2Actor.wrapped_icrc2_approve_batch(
return await* ICRCCall.wrapped_icrc2_approve_batch(
icrc2Actor,
batchSize,
approvals,
WrappedIcrc2Actor.icrc2_approve
);
};

Expand All @@ -58,11 +56,10 @@ module {
batchSize: Nat,
transfers: [ICRC2Interface.TransferFromArgs]
) : async* [{ #Ok : Nat; #Err : ICRC2Interface.TransferFromError }] {
return await* WrappedIcrc2Actor.wrapped_icrc2_transfer_from_batch(
return await* ICRCCall.wrapped_icrc2_transfer_from_batch(
icrc2Actor,
batchSize,
transfers,
WrappedIcrc2Actor.icrc2_transfer_from
);
};
};
Loading

0 comments on commit ce9c070

Please sign in to comment.