diff --git a/canisters/icrc/LICENSE b/canisters/icp/LICENSE
similarity index 100%
rename from canisters/icrc/LICENSE
rename to canisters/icp/LICENSE
diff --git a/canisters/ledger/NOTICE b/canisters/icp/NOTICE
similarity index 100%
rename from canisters/ledger/NOTICE
rename to canisters/icp/NOTICE
diff --git a/canisters/ledger/address/index.ts b/canisters/icp/address/index.ts
similarity index 96%
rename from canisters/ledger/address/index.ts
rename to canisters/icp/address/index.ts
index e579506f69..4f88118447 100755
--- a/canisters/ledger/address/index.ts
+++ b/canisters/icp/address/index.ts
@@ -2,13 +2,12 @@ import { getCrc32 } from '@dfinity/principal/lib/esm/utils/getCrc';
 import jsSHA from 'jssha';
 
 import { blob, Principal } from '../../../src/lib/experimental';
-import { Address } from '../index';
 
 // TODO we need to review these heavily
 export function hexAddressFromPrincipal(
     principal: Principal,
     subaccount: number
-): Address {
+): string {
     return addressFromPrincipal(principal, subaccount);
 }
 
@@ -22,7 +21,7 @@ export function binaryAddressFromPrincipal(
     );
 }
 
-export function binaryAddressFromAddress(address: Address): blob {
+export function binaryAddressFromAddress(address: string): blob {
     return Uint8Array.from(
         address.match(/.{1,2}/g)?.map((x) => parseInt(x, 16)) ?? []
     );
@@ -43,7 +42,7 @@ export function binaryAddressFromAddress(address: Address): blob {
 function addressFromPrincipal(
     principal: Principal,
     subaccount: number
-): Address {
+): string {
     const prefixBytes = new Uint8Array([
         10, 97, 99, 99, 111, 117, 110, 116, 45, 105, 100
     ]); // \0xAaccount-id
diff --git a/canisters/icp/index.ts b/canisters/icp/index.ts
new file mode 100644
index 0000000000..292d797cd3
--- /dev/null
+++ b/canisters/icp/index.ts
@@ -0,0 +1,1106 @@
+import { ActorMethod } from '@dfinity/agent';
+import { IDL } from '@dfinity/candid';
+import { Principal } from '@dfinity/principal';
+export interface Account {
+    owner: Principal;
+    subaccount: [] | [SubAccount];
+}
+export interface AccountBalanceArgs {
+    account: AccountIdentifier;
+}
+export interface AccountBalanceArgsDfx {
+    account: TextAccountIdentifier;
+}
+export type AccountIdentifier = Uint8Array | number[];
+export interface Allowance {
+    allowance: Icrc1Tokens;
+    expires_at: [] | [Icrc1Timestamp];
+}
+export interface AllowanceArgs {
+    account: Account;
+    spender: Account;
+}
+export interface ApproveArgs {
+    fee: [] | [Icrc1Tokens];
+    memo: [] | [Uint8Array | number[]];
+    from_subaccount: [] | [SubAccount];
+    created_at_time: [] | [Icrc1Timestamp];
+    amount: Icrc1Tokens;
+    expected_allowance: [] | [Icrc1Tokens];
+    expires_at: [] | [Icrc1Timestamp];
+    spender: Account;
+}
+export type ApproveError =
+    | {
+          GenericError: { message: string; error_code: bigint };
+      }
+    | { TemporarilyUnavailable: null }
+    | { Duplicate: { duplicate_of: Icrc1BlockIndex } }
+    | { BadFee: { expected_fee: Icrc1Tokens } }
+    | { AllowanceChanged: { current_allowance: Icrc1Tokens } }
+    | { CreatedInFuture: { ledger_time: bigint } }
+    | { TooOld: null }
+    | { Expired: { ledger_time: bigint } }
+    | { InsufficientFunds: { balance: Icrc1Tokens } };
+export type ApproveResult = { Ok: Icrc1BlockIndex } | { Err: ApproveError };
+export interface Archive {
+    canister_id: Principal;
+}
+export interface ArchiveOptions {
+    num_blocks_to_archive: bigint;
+    max_transactions_per_response: [] | [bigint];
+    trigger_threshold: bigint;
+    more_controller_ids: [] | [Array<Principal>];
+    max_message_size_bytes: [] | [bigint];
+    cycles_for_archive_creation: [] | [bigint];
+    node_max_memory_size_bytes: [] | [bigint];
+    controller_id: Principal;
+}
+export interface ArchivedBlocksRange {
+    callback: QueryArchiveFn;
+    start: BlockIndex;
+    length: bigint;
+}
+export interface ArchivedEncodedBlocksRange {
+    callback: [Principal, string];
+    start: bigint;
+    length: bigint;
+}
+export interface Archives {
+    archives: Array<Archive>;
+}
+export interface Block {
+    transaction: Transaction;
+    timestamp: TimeStamp;
+    parent_hash: [] | [Uint8Array | number[]];
+}
+export type BlockIndex = bigint;
+export interface BlockRange {
+    blocks: Array<Block>;
+}
+export interface DecimalsResult {
+    decimals: number;
+}
+export interface Duration {
+    secs: bigint;
+    nanos: number;
+}
+export interface FeatureFlags {
+    icrc2: boolean;
+}
+export interface GetBlocksArgs {
+    start: BlockIndex;
+    length: bigint;
+}
+export type Icrc1BlockIndex = bigint;
+export type Icrc1Timestamp = bigint;
+export type Icrc1Tokens = bigint;
+export type Icrc1TransferError =
+    | {
+          GenericError: { message: string; error_code: bigint };
+      }
+    | { TemporarilyUnavailable: null }
+    | { BadBurn: { min_burn_amount: Icrc1Tokens } }
+    | { Duplicate: { duplicate_of: Icrc1BlockIndex } }
+    | { BadFee: { expected_fee: Icrc1Tokens } }
+    | { CreatedInFuture: { ledger_time: bigint } }
+    | { TooOld: null }
+    | { InsufficientFunds: { balance: Icrc1Tokens } };
+export type Icrc1TransferResult =
+    | { Ok: Icrc1BlockIndex }
+    | { Err: Icrc1TransferError };
+export interface InitArgs {
+    send_whitelist: Array<Principal>;
+    token_symbol: [] | [string];
+    transfer_fee: [] | [Tokens];
+    minting_account: TextAccountIdentifier;
+    maximum_number_of_accounts: [] | [bigint];
+    accounts_overflow_trim_quantity: [] | [bigint];
+    transaction_window: [] | [Duration];
+    max_message_size_bytes: [] | [bigint];
+    icrc1_minting_account: [] | [Account];
+    archive_options: [] | [ArchiveOptions];
+    initial_values: Array<[TextAccountIdentifier, Tokens]>;
+    token_name: [] | [string];
+    feature_flags: [] | [FeatureFlags];
+}
+export type LedgerCanisterPayload =
+    | { Upgrade: [] | [UpgradeArgs] }
+    | { Init: InitArgs };
+export type Memo = bigint;
+export interface NameResult {
+    name: string;
+}
+export type Operation =
+    | {
+          Approve: {
+              fee: Tokens;
+              from: AccountIdentifier;
+              allowance_e8s: bigint;
+              allowance: Tokens;
+              expected_allowance: [] | [Tokens];
+              expires_at: [] | [TimeStamp];
+              spender: AccountIdentifier;
+          };
+      }
+    | {
+          Burn: {
+              from: AccountIdentifier;
+              amount: Tokens;
+              spender: [] | [AccountIdentifier];
+          };
+      }
+    | { Mint: { to: AccountIdentifier; amount: Tokens } }
+    | {
+          Transfer: {
+              to: AccountIdentifier;
+              fee: Tokens;
+              from: AccountIdentifier;
+              amount: Tokens;
+              spender: [] | [Uint8Array | number[]];
+          };
+      };
+export type QueryArchiveError =
+    | {
+          BadFirstBlockIndex: {
+              requested_index: BlockIndex;
+              first_valid_index: BlockIndex;
+          };
+      }
+    | { Other: { error_message: string; error_code: bigint } };
+export type QueryArchiveFn = ActorMethod<[GetBlocksArgs], QueryArchiveResult>;
+export type QueryArchiveResult =
+    | { Ok: BlockRange }
+    | { Err: QueryArchiveError };
+export interface QueryBlocksResponse {
+    certificate: [] | [Uint8Array | number[]];
+    blocks: Array<Block>;
+    chain_length: bigint;
+    first_block_index: BlockIndex;
+    archived_blocks: Array<ArchivedBlocksRange>;
+}
+export interface QueryEncodedBlocksResponse {
+    certificate: [] | [Uint8Array | number[]];
+    blocks: Array<Uint8Array | number[]>;
+    chain_length: bigint;
+    first_block_index: bigint;
+    archived_blocks: Array<ArchivedEncodedBlocksRange>;
+}
+export interface SendArgs {
+    to: TextAccountIdentifier;
+    fee: Tokens;
+    memo: Memo;
+    from_subaccount: [] | [SubAccount];
+    created_at_time: [] | [TimeStamp];
+    amount: Tokens;
+}
+export type SubAccount = Uint8Array | number[];
+export interface SymbolResult {
+    symbol: string;
+}
+export type TextAccountIdentifier = string;
+export interface TimeStamp {
+    timestamp_nanos: bigint;
+}
+export interface Tokens {
+    e8s: bigint;
+}
+export interface Transaction {
+    memo: Memo;
+    icrc1_memo: [] | [Uint8Array | number[]];
+    operation: [] | [Operation];
+    created_at_time: TimeStamp;
+}
+export interface TransferArg {
+    to: Account;
+    fee: [] | [Icrc1Tokens];
+    memo: [] | [Uint8Array | number[]];
+    from_subaccount: [] | [SubAccount];
+    created_at_time: [] | [Icrc1Timestamp];
+    amount: Icrc1Tokens;
+}
+export interface TransferArgs {
+    to: AccountIdentifier;
+    fee: Tokens;
+    memo: Memo;
+    from_subaccount: [] | [SubAccount];
+    created_at_time: [] | [TimeStamp];
+    amount: Tokens;
+}
+export type TransferError =
+    | {
+          TxTooOld: { allowed_window_nanos: bigint };
+      }
+    | { BadFee: { expected_fee: Tokens } }
+    | { TxDuplicate: { duplicate_of: BlockIndex } }
+    | { TxCreatedInFuture: null }
+    | { InsufficientFunds: { balance: Tokens } };
+export interface TransferFee {
+    transfer_fee: Tokens;
+}
+// eslint-disable-next-line
+export type TransferFeeArg = {};
+export interface TransferFromArgs {
+    to: Account;
+    fee: [] | [Icrc1Tokens];
+    spender_subaccount: [] | [SubAccount];
+    from: Account;
+    memo: [] | [Uint8Array | number[]];
+    created_at_time: [] | [Icrc1Timestamp];
+    amount: Icrc1Tokens;
+}
+export type TransferFromError =
+    | {
+          GenericError: { message: string; error_code: bigint };
+      }
+    | { TemporarilyUnavailable: null }
+    | { InsufficientAllowance: { allowance: Icrc1Tokens } }
+    | { BadBurn: { min_burn_amount: Icrc1Tokens } }
+    | { Duplicate: { duplicate_of: Icrc1BlockIndex } }
+    | { BadFee: { expected_fee: Icrc1Tokens } }
+    | { CreatedInFuture: { ledger_time: Icrc1Timestamp } }
+    | { TooOld: null }
+    | { InsufficientFunds: { balance: Icrc1Tokens } };
+export type TransferFromResult =
+    | { Ok: Icrc1BlockIndex }
+    | { Err: TransferFromError };
+export type TransferResult = { Ok: BlockIndex } | { Err: TransferError };
+export interface UpgradeArgs {
+    icrc1_minting_account: [] | [Account];
+    feature_flags: [] | [FeatureFlags];
+}
+export type Value =
+    | { Int: bigint }
+    | { Nat: bigint }
+    | { Blob: Uint8Array | number[] }
+    | { Text: string };
+export interface icrc21_consent_info {
+    metadata: icrc21_consent_message_metadata;
+    consent_message: icrc21_consent_message;
+}
+export type icrc21_consent_message =
+    | {
+          LineDisplayMessage: { pages: Array<{ lines: Array<string> }> };
+      }
+    | { GenericDisplayMessage: string };
+export interface icrc21_consent_message_metadata {
+    utc_offset_minutes: [] | [number];
+    language: string;
+}
+export interface icrc21_consent_message_request {
+    arg: Uint8Array | number[];
+    method: string;
+    user_preferences: icrc21_consent_message_spec;
+}
+export type icrc21_consent_message_response =
+    | { Ok: icrc21_consent_info }
+    | { Err: icrc21_error };
+export interface icrc21_consent_message_spec {
+    metadata: icrc21_consent_message_metadata;
+    device_spec:
+        | []
+        | [
+              | { GenericDisplay: null }
+              | {
+                    LineDisplay: {
+                        characters_per_line: number;
+                        lines_per_page: number;
+                    };
+                }
+          ];
+}
+export type icrc21_error =
+    | {
+          GenericError: { description: string; error_code: bigint };
+      }
+    | { InsufficientPayment: icrc21_error_info }
+    | { UnsupportedCanisterCall: icrc21_error_info }
+    | { ConsentMessageUnavailable: icrc21_error_info };
+export interface icrc21_error_info {
+    description: string;
+}
+export interface _SERVICE {
+    account_balance: ActorMethod<[AccountBalanceArgs], Tokens>;
+    account_balance_dfx: ActorMethod<[AccountBalanceArgsDfx], Tokens>;
+    account_identifier: ActorMethod<[Account], AccountIdentifier>;
+    archives: ActorMethod<[], Archives>;
+    decimals: ActorMethod<[], DecimalsResult>;
+    icrc10_supported_standards: ActorMethod<
+        [],
+        Array<{ url: string; name: string }>
+    >;
+    icrc1_balance_of: ActorMethod<[Account], Icrc1Tokens>;
+    icrc1_decimals: ActorMethod<[], number>;
+    icrc1_fee: ActorMethod<[], Icrc1Tokens>;
+    icrc1_metadata: ActorMethod<[], Array<[string, Value]>>;
+    icrc1_minting_account: ActorMethod<[], [] | [Account]>;
+    icrc1_name: ActorMethod<[], string>;
+    icrc1_supported_standards: ActorMethod<
+        [],
+        Array<{ url: string; name: string }>
+    >;
+    icrc1_symbol: ActorMethod<[], string>;
+    icrc1_total_supply: ActorMethod<[], Icrc1Tokens>;
+    icrc1_transfer: ActorMethod<[TransferArg], Icrc1TransferResult>;
+    icrc21_canister_call_consent_message: ActorMethod<
+        [icrc21_consent_message_request],
+        icrc21_consent_message_response
+    >;
+    icrc2_allowance: ActorMethod<[AllowanceArgs], Allowance>;
+    icrc2_approve: ActorMethod<[ApproveArgs], ApproveResult>;
+    icrc2_transfer_from: ActorMethod<[TransferFromArgs], TransferFromResult>;
+    name: ActorMethod<[], NameResult>;
+    query_blocks: ActorMethod<[GetBlocksArgs], QueryBlocksResponse>;
+    query_encoded_blocks: ActorMethod<
+        [GetBlocksArgs],
+        QueryEncodedBlocksResponse
+    >;
+    send_dfx: ActorMethod<[SendArgs], BlockIndex>;
+    symbol: ActorMethod<[], SymbolResult>;
+    transfer: ActorMethod<[TransferArgs], TransferResult>;
+    transfer_fee: ActorMethod<[TransferFeeArg], TransferFee>;
+}
+export type idlFactory = IDL.InterfaceFactory;
+export type init = (args: { IDL: typeof IDL }) => IDL.Type[];
+export const SubAccount = IDL.Vec(IDL.Nat8);
+export const Account = IDL.Record({
+    owner: IDL.Principal,
+    subaccount: IDL.Opt(SubAccount)
+});
+export const FeatureFlags = IDL.Record({ icrc2: IDL.Bool });
+export const UpgradeArgs = IDL.Record({
+    icrc1_minting_account: IDL.Opt(Account),
+    feature_flags: IDL.Opt(FeatureFlags)
+});
+export const Tokens = IDL.Record({ e8s: IDL.Nat64 });
+export const TextAccountIdentifier = IDL.Text;
+export const Duration = IDL.Record({ secs: IDL.Nat64, nanos: IDL.Nat32 });
+export const ArchiveOptions = IDL.Record({
+    num_blocks_to_archive: IDL.Nat64,
+    max_transactions_per_response: IDL.Opt(IDL.Nat64),
+    trigger_threshold: IDL.Nat64,
+    more_controller_ids: IDL.Opt(IDL.Vec(IDL.Principal)),
+    max_message_size_bytes: IDL.Opt(IDL.Nat64),
+    cycles_for_archive_creation: IDL.Opt(IDL.Nat64),
+    node_max_memory_size_bytes: IDL.Opt(IDL.Nat64),
+    controller_id: IDL.Principal
+});
+export const InitArgs = IDL.Record({
+    send_whitelist: IDL.Vec(IDL.Principal),
+    token_symbol: IDL.Opt(IDL.Text),
+    transfer_fee: IDL.Opt(Tokens),
+    minting_account: TextAccountIdentifier,
+    maximum_number_of_accounts: IDL.Opt(IDL.Nat64),
+    accounts_overflow_trim_quantity: IDL.Opt(IDL.Nat64),
+    transaction_window: IDL.Opt(Duration),
+    max_message_size_bytes: IDL.Opt(IDL.Nat64),
+    icrc1_minting_account: IDL.Opt(Account),
+    archive_options: IDL.Opt(ArchiveOptions),
+    initial_values: IDL.Vec(IDL.Tuple(TextAccountIdentifier, Tokens)),
+    token_name: IDL.Opt(IDL.Text),
+    feature_flags: IDL.Opt(FeatureFlags)
+});
+export const LedgerCanisterPayload = IDL.Variant({
+    Upgrade: IDL.Opt(UpgradeArgs),
+    Init: InitArgs
+});
+export const AccountIdentifier = IDL.Vec(IDL.Nat8);
+export const AccountBalanceArgs = IDL.Record({ account: AccountIdentifier });
+export const AccountBalanceArgsDfx = IDL.Record({
+    account: TextAccountIdentifier
+});
+export const Archive = IDL.Record({ canister_id: IDL.Principal });
+export const Archives = IDL.Record({ archives: IDL.Vec(Archive) });
+export const DecimalsResult = IDL.Record({ decimals: IDL.Nat32 });
+export const Icrc1Tokens = IDL.Nat;
+export const Value = IDL.Variant({
+    Int: IDL.Int,
+    Nat: IDL.Nat,
+    Blob: IDL.Vec(IDL.Nat8),
+    Text: IDL.Text
+});
+export const Icrc1Timestamp = IDL.Nat64;
+export const TransferArg = IDL.Record({
+    to: Account,
+    fee: IDL.Opt(Icrc1Tokens),
+    memo: IDL.Opt(IDL.Vec(IDL.Nat8)),
+    from_subaccount: IDL.Opt(SubAccount),
+    created_at_time: IDL.Opt(Icrc1Timestamp),
+    amount: Icrc1Tokens
+});
+export const Icrc1BlockIndex = IDL.Nat;
+export const Icrc1TransferError = IDL.Variant({
+    GenericError: IDL.Record({ message: IDL.Text, error_code: IDL.Nat }),
+    TemporarilyUnavailable: IDL.Null,
+    BadBurn: IDL.Record({ min_burn_amount: Icrc1Tokens }),
+    Duplicate: IDL.Record({ duplicate_of: Icrc1BlockIndex }),
+    BadFee: IDL.Record({ expected_fee: Icrc1Tokens }),
+    CreatedInFuture: IDL.Record({ ledger_time: IDL.Nat64 }),
+    TooOld: IDL.Null,
+    InsufficientFunds: IDL.Record({ balance: Icrc1Tokens })
+});
+export const Icrc1TransferResult = IDL.Variant({
+    Ok: Icrc1BlockIndex,
+    Err: Icrc1TransferError
+});
+export const icrc21_consent_message_metadata = IDL.Record({
+    utc_offset_minutes: IDL.Opt(IDL.Int16),
+    language: IDL.Text
+});
+export const icrc21_consent_message_spec = IDL.Record({
+    metadata: icrc21_consent_message_metadata,
+    device_spec: IDL.Opt(
+        IDL.Variant({
+            GenericDisplay: IDL.Null,
+            LineDisplay: IDL.Record({
+                characters_per_line: IDL.Nat16,
+                lines_per_page: IDL.Nat16
+            })
+        })
+    )
+});
+export const icrc21_consent_message_request = IDL.Record({
+    arg: IDL.Vec(IDL.Nat8),
+    method: IDL.Text,
+    user_preferences: icrc21_consent_message_spec
+});
+export const icrc21_consent_message = IDL.Variant({
+    LineDisplayMessage: IDL.Record({
+        pages: IDL.Vec(IDL.Record({ lines: IDL.Vec(IDL.Text) }))
+    }),
+    GenericDisplayMessage: IDL.Text
+});
+export const icrc21_consent_info = IDL.Record({
+    metadata: icrc21_consent_message_metadata,
+    consent_message: icrc21_consent_message
+});
+export const icrc21_error_info = IDL.Record({ description: IDL.Text });
+export const icrc21_error = IDL.Variant({
+    GenericError: IDL.Record({
+        description: IDL.Text,
+        error_code: IDL.Nat
+    }),
+    InsufficientPayment: icrc21_error_info,
+    UnsupportedCanisterCall: icrc21_error_info,
+    ConsentMessageUnavailable: icrc21_error_info
+});
+export const icrc21_consent_message_response = IDL.Variant({
+    Ok: icrc21_consent_info,
+    Err: icrc21_error
+});
+export const AllowanceArgs = IDL.Record({
+    account: Account,
+    spender: Account
+});
+export const Allowance = IDL.Record({
+    allowance: Icrc1Tokens,
+    expires_at: IDL.Opt(Icrc1Timestamp)
+});
+export const ApproveArgs = IDL.Record({
+    fee: IDL.Opt(Icrc1Tokens),
+    memo: IDL.Opt(IDL.Vec(IDL.Nat8)),
+    from_subaccount: IDL.Opt(SubAccount),
+    created_at_time: IDL.Opt(Icrc1Timestamp),
+    amount: Icrc1Tokens,
+    expected_allowance: IDL.Opt(Icrc1Tokens),
+    expires_at: IDL.Opt(Icrc1Timestamp),
+    spender: Account
+});
+export const ApproveError = IDL.Variant({
+    GenericError: IDL.Record({ message: IDL.Text, error_code: IDL.Nat }),
+    TemporarilyUnavailable: IDL.Null,
+    Duplicate: IDL.Record({ duplicate_of: Icrc1BlockIndex }),
+    BadFee: IDL.Record({ expected_fee: Icrc1Tokens }),
+    AllowanceChanged: IDL.Record({ current_allowance: Icrc1Tokens }),
+    CreatedInFuture: IDL.Record({ ledger_time: IDL.Nat64 }),
+    TooOld: IDL.Null,
+    Expired: IDL.Record({ ledger_time: IDL.Nat64 }),
+    InsufficientFunds: IDL.Record({ balance: Icrc1Tokens })
+});
+export const ApproveResult = IDL.Variant({
+    Ok: Icrc1BlockIndex,
+    Err: ApproveError
+});
+export const TransferFromArgs = IDL.Record({
+    to: Account,
+    fee: IDL.Opt(Icrc1Tokens),
+    spender_subaccount: IDL.Opt(SubAccount),
+    from: Account,
+    memo: IDL.Opt(IDL.Vec(IDL.Nat8)),
+    created_at_time: IDL.Opt(Icrc1Timestamp),
+    amount: Icrc1Tokens
+});
+export const TransferFromError = IDL.Variant({
+    GenericError: IDL.Record({ message: IDL.Text, error_code: IDL.Nat }),
+    TemporarilyUnavailable: IDL.Null,
+    InsufficientAllowance: IDL.Record({ allowance: Icrc1Tokens }),
+    BadBurn: IDL.Record({ min_burn_amount: Icrc1Tokens }),
+    Duplicate: IDL.Record({ duplicate_of: Icrc1BlockIndex }),
+    BadFee: IDL.Record({ expected_fee: Icrc1Tokens }),
+    CreatedInFuture: IDL.Record({ ledger_time: Icrc1Timestamp }),
+    TooOld: IDL.Null,
+    InsufficientFunds: IDL.Record({ balance: Icrc1Tokens })
+});
+export const TransferFromResult = IDL.Variant({
+    Ok: Icrc1BlockIndex,
+    Err: TransferFromError
+});
+export const NameResult = IDL.Record({ name: IDL.Text });
+export const BlockIndex = IDL.Nat64;
+export const GetBlocksArgs = IDL.Record({
+    start: BlockIndex,
+    length: IDL.Nat64
+});
+export const Memo = IDL.Nat64;
+export const TimeStamp = IDL.Record({ timestamp_nanos: IDL.Nat64 });
+export const Operation = IDL.Variant({
+    Approve: IDL.Record({
+        fee: Tokens,
+        from: AccountIdentifier,
+        allowance_e8s: IDL.Int,
+        allowance: Tokens,
+        expected_allowance: IDL.Opt(Tokens),
+        expires_at: IDL.Opt(TimeStamp),
+        spender: AccountIdentifier
+    }),
+    Burn: IDL.Record({
+        from: AccountIdentifier,
+        amount: Tokens,
+        spender: IDL.Opt(AccountIdentifier)
+    }),
+    Mint: IDL.Record({ to: AccountIdentifier, amount: Tokens }),
+    Transfer: IDL.Record({
+        to: AccountIdentifier,
+        fee: Tokens,
+        from: AccountIdentifier,
+        amount: Tokens,
+        spender: IDL.Opt(IDL.Vec(IDL.Nat8))
+    })
+});
+export const Transaction = IDL.Record({
+    memo: Memo,
+    icrc1_memo: IDL.Opt(IDL.Vec(IDL.Nat8)),
+    operation: IDL.Opt(Operation),
+    created_at_time: TimeStamp
+});
+export const Block = IDL.Record({
+    transaction: Transaction,
+    timestamp: TimeStamp,
+    parent_hash: IDL.Opt(IDL.Vec(IDL.Nat8))
+});
+export const BlockRange = IDL.Record({ blocks: IDL.Vec(Block) });
+export const QueryArchiveError = IDL.Variant({
+    BadFirstBlockIndex: IDL.Record({
+        requested_index: BlockIndex,
+        first_valid_index: BlockIndex
+    }),
+    Other: IDL.Record({
+        error_message: IDL.Text,
+        error_code: IDL.Nat64
+    })
+});
+export const QueryArchiveResult = IDL.Variant({
+    Ok: BlockRange,
+    Err: QueryArchiveError
+});
+export const QueryArchiveFn = IDL.Func(
+    [GetBlocksArgs],
+    [QueryArchiveResult],
+    ['query']
+);
+export const ArchivedBlocksRange = IDL.Record({
+    callback: QueryArchiveFn,
+    start: BlockIndex,
+    length: IDL.Nat64
+});
+export const QueryBlocksResponse = IDL.Record({
+    certificate: IDL.Opt(IDL.Vec(IDL.Nat8)),
+    blocks: IDL.Vec(Block),
+    chain_length: IDL.Nat64,
+    first_block_index: BlockIndex,
+    archived_blocks: IDL.Vec(ArchivedBlocksRange)
+});
+export const ArchivedEncodedBlocksRange = IDL.Record({
+    callback: IDL.Func(
+        [GetBlocksArgs],
+        [
+            IDL.Variant({
+                Ok: IDL.Vec(IDL.Vec(IDL.Nat8)),
+                Err: QueryArchiveError
+            })
+        ],
+        ['query']
+    ),
+    start: IDL.Nat64,
+    length: IDL.Nat64
+});
+export const QueryEncodedBlocksResponse = IDL.Record({
+    certificate: IDL.Opt(IDL.Vec(IDL.Nat8)),
+    blocks: IDL.Vec(IDL.Vec(IDL.Nat8)),
+    chain_length: IDL.Nat64,
+    first_block_index: IDL.Nat64,
+    archived_blocks: IDL.Vec(ArchivedEncodedBlocksRange)
+});
+export const SendArgs = IDL.Record({
+    to: TextAccountIdentifier,
+    fee: Tokens,
+    memo: Memo,
+    from_subaccount: IDL.Opt(SubAccount),
+    created_at_time: IDL.Opt(TimeStamp),
+    amount: Tokens
+});
+export const SymbolResult = IDL.Record({ symbol: IDL.Text });
+export const TransferArgs = IDL.Record({
+    to: AccountIdentifier,
+    fee: Tokens,
+    memo: Memo,
+    from_subaccount: IDL.Opt(SubAccount),
+    created_at_time: IDL.Opt(TimeStamp),
+    amount: Tokens
+});
+export const TransferError = IDL.Variant({
+    TxTooOld: IDL.Record({ allowed_window_nanos: IDL.Nat64 }),
+    BadFee: IDL.Record({ expected_fee: Tokens }),
+    TxDuplicate: IDL.Record({ duplicate_of: BlockIndex }),
+    TxCreatedInFuture: IDL.Null,
+    InsufficientFunds: IDL.Record({ balance: Tokens })
+});
+export const TransferResult = IDL.Variant({
+    Ok: BlockIndex,
+    Err: TransferError
+});
+export const TransferFeeArg = IDL.Record({});
+export const TransferFee = IDL.Record({ transfer_fee: Tokens });
+export const idlFactory: idlFactory = ({ IDL }) => {
+    const SubAccount = IDL.Vec(IDL.Nat8);
+    const Account = IDL.Record({
+        owner: IDL.Principal,
+        subaccount: IDL.Opt(SubAccount)
+    });
+    const FeatureFlags = IDL.Record({ icrc2: IDL.Bool });
+    const UpgradeArgs = IDL.Record({
+        icrc1_minting_account: IDL.Opt(Account),
+        feature_flags: IDL.Opt(FeatureFlags)
+    });
+    const Tokens = IDL.Record({ e8s: IDL.Nat64 });
+    const TextAccountIdentifier = IDL.Text;
+    const Duration = IDL.Record({ secs: IDL.Nat64, nanos: IDL.Nat32 });
+    const ArchiveOptions = IDL.Record({
+        num_blocks_to_archive: IDL.Nat64,
+        max_transactions_per_response: IDL.Opt(IDL.Nat64),
+        trigger_threshold: IDL.Nat64,
+        more_controller_ids: IDL.Opt(IDL.Vec(IDL.Principal)),
+        max_message_size_bytes: IDL.Opt(IDL.Nat64),
+        cycles_for_archive_creation: IDL.Opt(IDL.Nat64),
+        node_max_memory_size_bytes: IDL.Opt(IDL.Nat64),
+        controller_id: IDL.Principal
+    });
+    const InitArgs = IDL.Record({
+        send_whitelist: IDL.Vec(IDL.Principal),
+        token_symbol: IDL.Opt(IDL.Text),
+        transfer_fee: IDL.Opt(Tokens),
+        minting_account: TextAccountIdentifier,
+        maximum_number_of_accounts: IDL.Opt(IDL.Nat64),
+        accounts_overflow_trim_quantity: IDL.Opt(IDL.Nat64),
+        transaction_window: IDL.Opt(Duration),
+        max_message_size_bytes: IDL.Opt(IDL.Nat64),
+        icrc1_minting_account: IDL.Opt(Account),
+        archive_options: IDL.Opt(ArchiveOptions),
+        initial_values: IDL.Vec(IDL.Tuple(TextAccountIdentifier, Tokens)),
+        token_name: IDL.Opt(IDL.Text),
+        feature_flags: IDL.Opt(FeatureFlags)
+    });
+    // eslint-disable-next-line
+    const LedgerCanisterPayload = IDL.Variant({
+        Upgrade: IDL.Opt(UpgradeArgs),
+        Init: InitArgs
+    });
+    const AccountIdentifier = IDL.Vec(IDL.Nat8);
+    const AccountBalanceArgs = IDL.Record({ account: AccountIdentifier });
+    const AccountBalanceArgsDfx = IDL.Record({
+        account: TextAccountIdentifier
+    });
+    const Archive = IDL.Record({ canister_id: IDL.Principal });
+    const Archives = IDL.Record({ archives: IDL.Vec(Archive) });
+    const DecimalsResult = IDL.Record({ decimals: IDL.Nat32 });
+    const Icrc1Tokens = IDL.Nat;
+    const Value = IDL.Variant({
+        Int: IDL.Int,
+        Nat: IDL.Nat,
+        Blob: IDL.Vec(IDL.Nat8),
+        Text: IDL.Text
+    });
+    const Icrc1Timestamp = IDL.Nat64;
+    const TransferArg = IDL.Record({
+        to: Account,
+        fee: IDL.Opt(Icrc1Tokens),
+        memo: IDL.Opt(IDL.Vec(IDL.Nat8)),
+        from_subaccount: IDL.Opt(SubAccount),
+        created_at_time: IDL.Opt(Icrc1Timestamp),
+        amount: Icrc1Tokens
+    });
+    const Icrc1BlockIndex = IDL.Nat;
+    const Icrc1TransferError = IDL.Variant({
+        GenericError: IDL.Record({
+            message: IDL.Text,
+            error_code: IDL.Nat
+        }),
+        TemporarilyUnavailable: IDL.Null,
+        BadBurn: IDL.Record({ min_burn_amount: Icrc1Tokens }),
+        Duplicate: IDL.Record({ duplicate_of: Icrc1BlockIndex }),
+        BadFee: IDL.Record({ expected_fee: Icrc1Tokens }),
+        CreatedInFuture: IDL.Record({ ledger_time: IDL.Nat64 }),
+        TooOld: IDL.Null,
+        InsufficientFunds: IDL.Record({ balance: Icrc1Tokens })
+    });
+    const Icrc1TransferResult = IDL.Variant({
+        Ok: Icrc1BlockIndex,
+        Err: Icrc1TransferError
+    });
+    const icrc21_consent_message_metadata = IDL.Record({
+        utc_offset_minutes: IDL.Opt(IDL.Int16),
+        language: IDL.Text
+    });
+    const icrc21_consent_message_spec = IDL.Record({
+        metadata: icrc21_consent_message_metadata,
+        device_spec: IDL.Opt(
+            IDL.Variant({
+                GenericDisplay: IDL.Null,
+                LineDisplay: IDL.Record({
+                    characters_per_line: IDL.Nat16,
+                    lines_per_page: IDL.Nat16
+                })
+            })
+        )
+    });
+    const icrc21_consent_message_request = IDL.Record({
+        arg: IDL.Vec(IDL.Nat8),
+        method: IDL.Text,
+        user_preferences: icrc21_consent_message_spec
+    });
+    const icrc21_consent_message = IDL.Variant({
+        LineDisplayMessage: IDL.Record({
+            pages: IDL.Vec(IDL.Record({ lines: IDL.Vec(IDL.Text) }))
+        }),
+        GenericDisplayMessage: IDL.Text
+    });
+    const icrc21_consent_info = IDL.Record({
+        metadata: icrc21_consent_message_metadata,
+        consent_message: icrc21_consent_message
+    });
+    const icrc21_error_info = IDL.Record({ description: IDL.Text });
+    const icrc21_error = IDL.Variant({
+        GenericError: IDL.Record({
+            description: IDL.Text,
+            error_code: IDL.Nat
+        }),
+        InsufficientPayment: icrc21_error_info,
+        UnsupportedCanisterCall: icrc21_error_info,
+        ConsentMessageUnavailable: icrc21_error_info
+    });
+    const icrc21_consent_message_response = IDL.Variant({
+        Ok: icrc21_consent_info,
+        Err: icrc21_error
+    });
+    const AllowanceArgs = IDL.Record({
+        account: Account,
+        spender: Account
+    });
+    const Allowance = IDL.Record({
+        allowance: Icrc1Tokens,
+        expires_at: IDL.Opt(Icrc1Timestamp)
+    });
+    const ApproveArgs = IDL.Record({
+        fee: IDL.Opt(Icrc1Tokens),
+        memo: IDL.Opt(IDL.Vec(IDL.Nat8)),
+        from_subaccount: IDL.Opt(SubAccount),
+        created_at_time: IDL.Opt(Icrc1Timestamp),
+        amount: Icrc1Tokens,
+        expected_allowance: IDL.Opt(Icrc1Tokens),
+        expires_at: IDL.Opt(Icrc1Timestamp),
+        spender: Account
+    });
+    const ApproveError = IDL.Variant({
+        GenericError: IDL.Record({
+            message: IDL.Text,
+            error_code: IDL.Nat
+        }),
+        TemporarilyUnavailable: IDL.Null,
+        Duplicate: IDL.Record({ duplicate_of: Icrc1BlockIndex }),
+        BadFee: IDL.Record({ expected_fee: Icrc1Tokens }),
+        AllowanceChanged: IDL.Record({ current_allowance: Icrc1Tokens }),
+        CreatedInFuture: IDL.Record({ ledger_time: IDL.Nat64 }),
+        TooOld: IDL.Null,
+        Expired: IDL.Record({ ledger_time: IDL.Nat64 }),
+        InsufficientFunds: IDL.Record({ balance: Icrc1Tokens })
+    });
+    const ApproveResult = IDL.Variant({
+        Ok: Icrc1BlockIndex,
+        Err: ApproveError
+    });
+    const TransferFromArgs = IDL.Record({
+        to: Account,
+        fee: IDL.Opt(Icrc1Tokens),
+        spender_subaccount: IDL.Opt(SubAccount),
+        from: Account,
+        memo: IDL.Opt(IDL.Vec(IDL.Nat8)),
+        created_at_time: IDL.Opt(Icrc1Timestamp),
+        amount: Icrc1Tokens
+    });
+    const TransferFromError = IDL.Variant({
+        GenericError: IDL.Record({
+            message: IDL.Text,
+            error_code: IDL.Nat
+        }),
+        TemporarilyUnavailable: IDL.Null,
+        InsufficientAllowance: IDL.Record({ allowance: Icrc1Tokens }),
+        BadBurn: IDL.Record({ min_burn_amount: Icrc1Tokens }),
+        Duplicate: IDL.Record({ duplicate_of: Icrc1BlockIndex }),
+        BadFee: IDL.Record({ expected_fee: Icrc1Tokens }),
+        CreatedInFuture: IDL.Record({ ledger_time: Icrc1Timestamp }),
+        TooOld: IDL.Null,
+        InsufficientFunds: IDL.Record({ balance: Icrc1Tokens })
+    });
+    const TransferFromResult = IDL.Variant({
+        Ok: Icrc1BlockIndex,
+        Err: TransferFromError
+    });
+    const NameResult = IDL.Record({ name: IDL.Text });
+    const BlockIndex = IDL.Nat64;
+    const GetBlocksArgs = IDL.Record({
+        start: BlockIndex,
+        length: IDL.Nat64
+    });
+    const Memo = IDL.Nat64;
+    const TimeStamp = IDL.Record({ timestamp_nanos: IDL.Nat64 });
+    const Operation = IDL.Variant({
+        Approve: IDL.Record({
+            fee: Tokens,
+            from: AccountIdentifier,
+            allowance_e8s: IDL.Int,
+            allowance: Tokens,
+            expected_allowance: IDL.Opt(Tokens),
+            expires_at: IDL.Opt(TimeStamp),
+            spender: AccountIdentifier
+        }),
+        Burn: IDL.Record({
+            from: AccountIdentifier,
+            amount: Tokens,
+            spender: IDL.Opt(AccountIdentifier)
+        }),
+        Mint: IDL.Record({ to: AccountIdentifier, amount: Tokens }),
+        Transfer: IDL.Record({
+            to: AccountIdentifier,
+            fee: Tokens,
+            from: AccountIdentifier,
+            amount: Tokens,
+            spender: IDL.Opt(IDL.Vec(IDL.Nat8))
+        })
+    });
+    const Transaction = IDL.Record({
+        memo: Memo,
+        icrc1_memo: IDL.Opt(IDL.Vec(IDL.Nat8)),
+        operation: IDL.Opt(Operation),
+        created_at_time: TimeStamp
+    });
+    const Block = IDL.Record({
+        transaction: Transaction,
+        timestamp: TimeStamp,
+        parent_hash: IDL.Opt(IDL.Vec(IDL.Nat8))
+    });
+    const BlockRange = IDL.Record({ blocks: IDL.Vec(Block) });
+    const QueryArchiveError = IDL.Variant({
+        BadFirstBlockIndex: IDL.Record({
+            requested_index: BlockIndex,
+            first_valid_index: BlockIndex
+        }),
+        Other: IDL.Record({
+            error_message: IDL.Text,
+            error_code: IDL.Nat64
+        })
+    });
+    const QueryArchiveResult = IDL.Variant({
+        Ok: BlockRange,
+        Err: QueryArchiveError
+    });
+    const QueryArchiveFn = IDL.Func(
+        [GetBlocksArgs],
+        [QueryArchiveResult],
+        ['query']
+    );
+    const ArchivedBlocksRange = IDL.Record({
+        callback: QueryArchiveFn,
+        start: BlockIndex,
+        length: IDL.Nat64
+    });
+    const QueryBlocksResponse = IDL.Record({
+        certificate: IDL.Opt(IDL.Vec(IDL.Nat8)),
+        blocks: IDL.Vec(Block),
+        chain_length: IDL.Nat64,
+        first_block_index: BlockIndex,
+        archived_blocks: IDL.Vec(ArchivedBlocksRange)
+    });
+    const ArchivedEncodedBlocksRange = IDL.Record({
+        callback: IDL.Func(
+            [GetBlocksArgs],
+            [
+                IDL.Variant({
+                    Ok: IDL.Vec(IDL.Vec(IDL.Nat8)),
+                    Err: QueryArchiveError
+                })
+            ],
+            ['query']
+        ),
+        start: IDL.Nat64,
+        length: IDL.Nat64
+    });
+    const QueryEncodedBlocksResponse = IDL.Record({
+        certificate: IDL.Opt(IDL.Vec(IDL.Nat8)),
+        blocks: IDL.Vec(IDL.Vec(IDL.Nat8)),
+        chain_length: IDL.Nat64,
+        first_block_index: IDL.Nat64,
+        archived_blocks: IDL.Vec(ArchivedEncodedBlocksRange)
+    });
+    const SendArgs = IDL.Record({
+        to: TextAccountIdentifier,
+        fee: Tokens,
+        memo: Memo,
+        from_subaccount: IDL.Opt(SubAccount),
+        created_at_time: IDL.Opt(TimeStamp),
+        amount: Tokens
+    });
+    const SymbolResult = IDL.Record({ symbol: IDL.Text });
+    const TransferArgs = IDL.Record({
+        to: AccountIdentifier,
+        fee: Tokens,
+        memo: Memo,
+        from_subaccount: IDL.Opt(SubAccount),
+        created_at_time: IDL.Opt(TimeStamp),
+        amount: Tokens
+    });
+    const TransferError = IDL.Variant({
+        TxTooOld: IDL.Record({ allowed_window_nanos: IDL.Nat64 }),
+        BadFee: IDL.Record({ expected_fee: Tokens }),
+        TxDuplicate: IDL.Record({ duplicate_of: BlockIndex }),
+        TxCreatedInFuture: IDL.Null,
+        InsufficientFunds: IDL.Record({ balance: Tokens })
+    });
+    const TransferResult = IDL.Variant({
+        Ok: BlockIndex,
+        Err: TransferError
+    });
+    const TransferFeeArg = IDL.Record({});
+    const TransferFee = IDL.Record({ transfer_fee: Tokens });
+    return IDL.Service({
+        account_balance: IDL.Func([AccountBalanceArgs], [Tokens], ['query']),
+        account_balance_dfx: IDL.Func(
+            [AccountBalanceArgsDfx],
+            [Tokens],
+            ['query']
+        ),
+        account_identifier: IDL.Func([Account], [AccountIdentifier], ['query']),
+        archives: IDL.Func([], [Archives], ['query']),
+        decimals: IDL.Func([], [DecimalsResult], ['query']),
+        icrc10_supported_standards: IDL.Func(
+            [],
+            [IDL.Vec(IDL.Record({ url: IDL.Text, name: IDL.Text }))],
+            ['query']
+        ),
+        icrc1_balance_of: IDL.Func([Account], [Icrc1Tokens], ['query']),
+        icrc1_decimals: IDL.Func([], [IDL.Nat8], ['query']),
+        icrc1_fee: IDL.Func([], [Icrc1Tokens], ['query']),
+        icrc1_metadata: IDL.Func(
+            [],
+            [IDL.Vec(IDL.Tuple(IDL.Text, Value))],
+            ['query']
+        ),
+        icrc1_minting_account: IDL.Func([], [IDL.Opt(Account)], ['query']),
+        icrc1_name: IDL.Func([], [IDL.Text], ['query']),
+        icrc1_supported_standards: IDL.Func(
+            [],
+            [IDL.Vec(IDL.Record({ url: IDL.Text, name: IDL.Text }))],
+            ['query']
+        ),
+        icrc1_symbol: IDL.Func([], [IDL.Text], ['query']),
+        icrc1_total_supply: IDL.Func([], [Icrc1Tokens], ['query']),
+        icrc1_transfer: IDL.Func([TransferArg], [Icrc1TransferResult], []),
+        icrc21_canister_call_consent_message: IDL.Func(
+            [icrc21_consent_message_request],
+            [icrc21_consent_message_response],
+            []
+        ),
+        icrc2_allowance: IDL.Func([AllowanceArgs], [Allowance], ['query']),
+        icrc2_approve: IDL.Func([ApproveArgs], [ApproveResult], []),
+        icrc2_transfer_from: IDL.Func(
+            [TransferFromArgs],
+            [TransferFromResult],
+            []
+        ),
+        name: IDL.Func([], [NameResult], ['query']),
+        query_blocks: IDL.Func(
+            [GetBlocksArgs],
+            [QueryBlocksResponse],
+            ['query']
+        ),
+        query_encoded_blocks: IDL.Func(
+            [GetBlocksArgs],
+            [QueryEncodedBlocksResponse],
+            ['query']
+        ),
+        send_dfx: IDL.Func([SendArgs], [BlockIndex], []),
+        symbol: IDL.Func([], [SymbolResult], ['query']),
+        transfer: IDL.Func([TransferArgs], [TransferResult], []),
+        transfer_fee: IDL.Func([TransferFeeArg], [TransferFee], ['query'])
+    });
+};
+export const init: init = ({ IDL }) => {
+    const SubAccount = IDL.Vec(IDL.Nat8);
+    const Account = IDL.Record({
+        owner: IDL.Principal,
+        subaccount: IDL.Opt(SubAccount)
+    });
+    const FeatureFlags = IDL.Record({ icrc2: IDL.Bool });
+    const UpgradeArgs = IDL.Record({
+        icrc1_minting_account: IDL.Opt(Account),
+        feature_flags: IDL.Opt(FeatureFlags)
+    });
+    const Tokens = IDL.Record({ e8s: IDL.Nat64 });
+    const TextAccountIdentifier = IDL.Text;
+    const Duration = IDL.Record({ secs: IDL.Nat64, nanos: IDL.Nat32 });
+    const ArchiveOptions = IDL.Record({
+        num_blocks_to_archive: IDL.Nat64,
+        max_transactions_per_response: IDL.Opt(IDL.Nat64),
+        trigger_threshold: IDL.Nat64,
+        more_controller_ids: IDL.Opt(IDL.Vec(IDL.Principal)),
+        max_message_size_bytes: IDL.Opt(IDL.Nat64),
+        cycles_for_archive_creation: IDL.Opt(IDL.Nat64),
+        node_max_memory_size_bytes: IDL.Opt(IDL.Nat64),
+        controller_id: IDL.Principal
+    });
+    const InitArgs = IDL.Record({
+        send_whitelist: IDL.Vec(IDL.Principal),
+        token_symbol: IDL.Opt(IDL.Text),
+        transfer_fee: IDL.Opt(Tokens),
+        minting_account: TextAccountIdentifier,
+        maximum_number_of_accounts: IDL.Opt(IDL.Nat64),
+        accounts_overflow_trim_quantity: IDL.Opt(IDL.Nat64),
+        transaction_window: IDL.Opt(Duration),
+        max_message_size_bytes: IDL.Opt(IDL.Nat64),
+        icrc1_minting_account: IDL.Opt(Account),
+        archive_options: IDL.Opt(ArchiveOptions),
+        initial_values: IDL.Vec(IDL.Tuple(TextAccountIdentifier, Tokens)),
+        token_name: IDL.Opt(IDL.Text),
+        feature_flags: IDL.Opt(FeatureFlags)
+    });
+    const LedgerCanisterPayload = IDL.Variant({
+        Upgrade: IDL.Opt(UpgradeArgs),
+        Init: InitArgs
+    });
+    return [LedgerCanisterPayload];
+};
+
+export {
+    binaryAddressFromAddress,
+    binaryAddressFromPrincipal,
+    hexAddressFromPrincipal
+} from './address';
diff --git a/canisters/icp/ledger.did b/canisters/icp/ledger.did
new file mode 100644
index 0000000000..b512f77225
--- /dev/null
+++ b/canisters/icp/ledger.did
@@ -0,0 +1,555 @@
+// Taken from: https://github.com/dfinity/ic/blob/release-2024-09-12_01-30-canister-snapshots-hotfix-deprecated-assert/rs/rosetta-api/icp_ledger/ledger.did
+
+// This is the official Ledger interface that is guaranteed to be backward compatible.
+
+// Amount of tokens, measured in 10^-8 of a token.
+type Tokens = record {
+     e8s : nat64;
+};
+
+// Number of nanoseconds from the UNIX epoch in UTC timezone.
+type TimeStamp = record {
+    timestamp_nanos: nat64;
+};
+
+// AccountIdentifier is a 32-byte array.
+// The first 4 bytes is big-endian encoding of a CRC32 checksum of the last 28 bytes.
+type AccountIdentifier = blob;
+
+// Subaccount is an arbitrary 32-byte byte array.
+// Ledger uses subaccounts to compute the source address, which enables one
+// principal to control multiple ledger accounts.
+type SubAccount = blob;
+
+// Sequence number of a block produced by the ledger.
+type BlockIndex = nat64;
+
+type Transaction = record {
+    memo : Memo;
+    icrc1_memo: opt blob;
+    operation : opt Operation;
+    created_at_time : TimeStamp;
+};
+
+// An arbitrary number associated with a transaction.
+// The caller can set it in a `transfer` call as a correlation identifier.
+type Memo = nat64;
+
+// Arguments for the `transfer` call.
+type TransferArgs = record {
+    // Transaction memo.
+    // See comments for the `Memo` type.
+    memo: Memo;
+    // The amount that the caller wants to transfer to the destination address.
+    amount: Tokens;
+    // The amount that the caller pays for the transaction.
+    // Must be 10000 e8s.
+    fee: Tokens;
+    // The subaccount from which the caller wants to transfer funds.
+    // If null, the ledger uses the default (all zeros) subaccount to compute the source address.
+    // See comments for the `SubAccount` type.
+    from_subaccount: opt SubAccount;
+    // The destination account.
+    // If the transfer is successful, the balance of this address increases by `amount`.
+    to: AccountIdentifier;
+    // The point in time when the caller created this request.
+    // If null, the ledger uses current IC time as the timestamp.
+    created_at_time: opt TimeStamp;
+};
+
+type TransferError = variant {
+    // The fee that the caller specified in the transfer request was not the one that ledger expects.
+    // The caller can change the transfer fee to the `expected_fee` and retry the request.
+    BadFee : record { expected_fee : Tokens; };
+    // The account specified by the caller doesn't have enough funds.
+    InsufficientFunds : record { balance: Tokens; };
+    // The request is too old.
+    // The ledger only accepts requests created within 24 hours window.
+    // This is a non-recoverable error.
+    TxTooOld : record { allowed_window_nanos: nat64 };
+    // The caller specified `created_at_time` that is too far in future.
+    // The caller can retry the request later.
+    TxCreatedInFuture : null;
+    // The ledger has already executed the request.
+    // `duplicate_of` field is equal to the index of the block containing the original transaction.
+    TxDuplicate : record { duplicate_of: BlockIndex; }
+};
+
+type TransferResult = variant {
+    Ok : BlockIndex;
+    Err : TransferError;
+};
+
+// Arguments for the `account_balance` call.
+type AccountBalanceArgs = record {
+    account: AccountIdentifier;
+};
+
+type TransferFeeArg = record {};
+
+type TransferFee = record {
+    // The fee to pay to perform a transfer
+    transfer_fee: Tokens;
+};
+
+type GetBlocksArgs = record {
+    // The index of the first block to fetch.
+    start : BlockIndex;
+    // Max number of blocks to fetch.
+    length : nat64;
+};
+
+type Operation = variant {
+    Mint : record {
+        to : AccountIdentifier;
+        amount : Tokens;
+    };
+    Burn : record {
+        from : AccountIdentifier;
+        spender : opt AccountIdentifier;
+        amount : Tokens;
+    };
+    Transfer : record {
+        from : AccountIdentifier;
+        to : AccountIdentifier;
+        amount : Tokens;
+        fee : Tokens;
+        spender : opt vec nat8;
+    };
+    Approve : record {
+        from : AccountIdentifier;
+        spender : AccountIdentifier;
+        // This field is deprecated and should not be used.
+        allowance_e8s : int;
+        allowance: Tokens;
+        fee : Tokens;
+        expires_at : opt TimeStamp;
+        expected_allowance : opt Tokens;
+    };
+};
+
+ 
+
+type Block = record {
+    parent_hash : opt blob;
+    transaction : Transaction;
+    timestamp : TimeStamp;
+};
+
+// A prefix of the block range specified in the [GetBlocksArgs] request.
+type BlockRange = record {
+    // A prefix of the requested block range.
+    // The index of the first block is equal to [GetBlocksArgs.from].
+    //
+    // Note that the number of blocks might be less than the requested
+    // [GetBlocksArgs.len] for various reasons, for example:
+    //
+    // 1. The query might have hit the replica with an outdated state
+    //    that doesn't have the full block range yet.
+    // 2. The requested range is too large to fit into a single reply.
+    //
+    // NOTE: the list of blocks can be empty if:
+    // 1. [GetBlocksArgs.len] was zero.
+    // 2. [GetBlocksArgs.from] was larger than the last block known to the canister.
+    blocks : vec Block;
+};
+
+// An error indicating that the arguments passed to [QueryArchiveFn] were invalid.
+type QueryArchiveError = variant {
+    // [GetBlocksArgs.from] argument was smaller than the first block
+    // served by the canister that received the request.
+    BadFirstBlockIndex : record {
+        requested_index : BlockIndex;
+        first_valid_index : BlockIndex;
+    };
+
+    // Reserved for future use.
+    Other : record {
+        error_code : nat64;
+        error_message : text;
+    };
+};
+
+type QueryArchiveResult = variant {
+    // Successfully fetched zero or more blocks.
+    Ok : BlockRange;
+    // The [GetBlocksArgs] request was invalid.
+    Err : QueryArchiveError;
+};
+
+// A function that is used for fetching archived ledger blocks.
+type QueryArchiveFn = func (GetBlocksArgs) -> (QueryArchiveResult) query;
+
+// The result of a "query_blocks" call.
+//
+// The structure of the result is somewhat complicated because the main ledger canister might
+// not have all the blocks that the caller requested: One or more "archive" canisters might
+// store some of the requested blocks.
+//
+// Note: as of Q4 2021 when this interface is authored, the IC doesn't support making nested 
+// query calls within a query call.
+type QueryBlocksResponse = record {
+    // The total number of blocks in the chain.
+    // If the chain length is positive, the index of the last block is `chain_len - 1`.
+    chain_length : nat64;
+
+    // System certificate for the hash of the latest block in the chain.
+    // Only present if `query_blocks` is called in a non-replicated query context.
+    certificate : opt blob;
+
+    // List of blocks that were available in the ledger when it processed the call.
+    //
+    // The blocks form a contiguous range, with the first block having index
+    // [first_block_index] (see below), and the last block having index
+    // [first_block_index] + len(blocks) - 1.
+    //
+    // The block range can be an arbitrary sub-range of the originally requested range.
+    blocks : vec Block;
+
+    // The index of the first block in "blocks".
+    // If the blocks vector is empty, the exact value of this field is not specified.
+    first_block_index : BlockIndex;
+
+    // Encoding of instructions for fetching archived blocks whose indices fall into the
+    // requested range.
+    //
+    // For each entry `e` in [archived_blocks], `[e.from, e.from + len)` is a sub-range
+    // of the originally requested block range.
+    archived_blocks : vec ArchivedBlocksRange;
+};
+
+type ArchivedBlocksRange = record {
+    // The index of the first archived block that can be fetched using the callback.
+    start : BlockIndex;
+
+    // The number of blocks that can be fetch using the callback.
+    length : nat64;
+
+    // The function that should be called to fetch the archived blocks.
+    // The range of the blocks accessible using this function is given by [from]
+    // and [len] fields above.
+    callback : QueryArchiveFn;
+};
+
+type ArchivedEncodedBlocksRange = record {
+    callback : func (GetBlocksArgs) -> (
+        variant { Ok : vec blob; Err : QueryArchiveError },
+        ) query;
+    start : nat64;
+    length : nat64;
+};
+
+type QueryEncodedBlocksResponse = record {
+    certificate : opt blob;
+    blocks : vec blob;
+    chain_length : nat64;
+    first_block_index : nat64;
+    archived_blocks : vec ArchivedEncodedBlocksRange;
+};
+
+type Archive = record {
+    canister_id: principal;
+};
+
+type Archives = record {
+    archives: vec Archive;
+};
+
+type Duration = record {
+    secs: nat64;
+    nanos: nat32;
+};
+
+type ArchiveOptions = record {
+    trigger_threshold : nat64;
+    num_blocks_to_archive : nat64;
+    node_max_memory_size_bytes : opt nat64;
+    max_message_size_bytes : opt nat64;
+    controller_id : principal;
+    more_controller_ids: opt vec principal;
+    cycles_for_archive_creation : opt nat64;
+    max_transactions_per_response : opt nat64;
+};
+
+// Account identifier encoded as a 64-byte ASCII hex string.
+type TextAccountIdentifier = text;
+
+// Arguments for the `send_dfx` call.
+type SendArgs = record {
+    memo: Memo;
+    amount: Tokens;
+    fee: Tokens;
+    from_subaccount: opt SubAccount;
+    to: TextAccountIdentifier;
+    created_at_time: opt TimeStamp;
+};
+
+type AccountBalanceArgsDfx = record {
+    account: TextAccountIdentifier;
+};
+
+type FeatureFlags = record {
+    icrc2 : bool;
+};
+
+type InitArgs = record {
+    minting_account: TextAccountIdentifier;
+    icrc1_minting_account: opt Account;
+    initial_values: vec record {TextAccountIdentifier; Tokens};
+    max_message_size_bytes: opt nat64;
+    transaction_window: opt Duration;
+    archive_options: opt ArchiveOptions;
+    send_whitelist: vec principal;
+    transfer_fee: opt Tokens;
+    token_symbol: opt text;
+    token_name: opt text;
+    feature_flags : opt FeatureFlags;
+    maximum_number_of_accounts : opt nat64;
+    accounts_overflow_trim_quantity: opt nat64;
+};
+
+type Icrc1BlockIndex = nat;
+// Number of nanoseconds since the UNIX epoch in UTC timezone.
+type Icrc1Timestamp = nat64;
+type Icrc1Tokens = nat;
+
+type Account = record {
+    owner : principal;
+    subaccount : opt SubAccount;
+};
+
+type TransferArg = record {
+    from_subaccount : opt SubAccount;
+    to : Account;
+    amount : Icrc1Tokens;
+    fee : opt Icrc1Tokens;
+    memo : opt blob;
+    created_at_time: opt Icrc1Timestamp;
+};
+
+type Icrc1TransferError = variant {
+    BadFee : record { expected_fee : Icrc1Tokens };
+    BadBurn : record { min_burn_amount : Icrc1Tokens };
+    InsufficientFunds : record { balance : Icrc1Tokens };
+    TooOld;
+    CreatedInFuture : record { ledger_time : nat64 };
+    TemporarilyUnavailable;
+    Duplicate : record { duplicate_of : Icrc1BlockIndex };
+    GenericError : record { error_code : nat; message : text };
+};
+
+type Icrc1TransferResult = variant {
+    Ok : Icrc1BlockIndex;
+    Err : Icrc1TransferError;
+};
+
+// The value returned from the [icrc1_metadata] endpoint.
+type Value = variant {
+    Nat : nat;
+    Int : int;
+    Text : text;
+    Blob : blob;
+};
+
+type UpgradeArgs = record {
+  icrc1_minting_account : opt Account;
+  feature_flags : opt FeatureFlags;
+};
+
+type LedgerCanisterPayload = variant {
+    Init: InitArgs;
+    Upgrade: opt UpgradeArgs;
+};
+
+type ApproveArgs = record {
+    from_subaccount : opt SubAccount;
+    spender : Account;
+    amount : Icrc1Tokens;
+    expected_allowance : opt Icrc1Tokens;
+    expires_at : opt Icrc1Timestamp;
+    fee : opt Icrc1Tokens;
+    memo : opt blob;
+    created_at_time: opt Icrc1Timestamp;
+};
+
+type ApproveError = variant {
+    BadFee : record { expected_fee : Icrc1Tokens };
+    InsufficientFunds : record { balance : Icrc1Tokens };
+    AllowanceChanged : record { current_allowance : Icrc1Tokens };
+    Expired : record { ledger_time : nat64 };
+    TooOld;
+    CreatedInFuture : record { ledger_time : nat64 };
+    Duplicate : record { duplicate_of : Icrc1BlockIndex };
+    TemporarilyUnavailable;
+    GenericError : record { error_code : nat; message : text };
+};
+
+type ApproveResult = variant {
+    Ok : Icrc1BlockIndex;
+    Err : ApproveError;
+};
+
+type AllowanceArgs = record {
+    account : Account;
+    spender : Account;
+};
+
+type Allowance = record {
+    allowance : Icrc1Tokens;
+    expires_at : opt Icrc1Timestamp;
+};
+
+type TransferFromArgs = record {
+    spender_subaccount : opt SubAccount;
+    from : Account;
+    to : Account;
+    amount : Icrc1Tokens;
+    fee : opt Icrc1Tokens;
+    memo : opt blob;
+    created_at_time: opt Icrc1Timestamp;
+};
+
+type TransferFromResult = variant {
+    Ok : Icrc1BlockIndex;
+    Err : TransferFromError;
+};
+
+type TransferFromError = variant {
+    BadFee : record { expected_fee : Icrc1Tokens };
+    BadBurn : record { min_burn_amount : Icrc1Tokens };
+    InsufficientFunds : record { balance : Icrc1Tokens };
+    InsufficientAllowance : record { allowance : Icrc1Tokens };
+    TooOld;
+    CreatedInFuture : record { ledger_time : Icrc1Timestamp };
+    Duplicate : record { duplicate_of : Icrc1BlockIndex };
+    TemporarilyUnavailable;
+    GenericError : record { error_code : nat; message : text };
+};
+
+type icrc21_consent_message_metadata = record {
+    language: text;
+    utc_offset_minutes: opt int16;
+};
+
+type icrc21_consent_message_spec = record {
+    metadata: icrc21_consent_message_metadata;
+    device_spec: opt variant {
+        GenericDisplay;
+        LineDisplay: record {
+            characters_per_line: nat16;
+            lines_per_page: nat16;
+        };
+    };
+};
+
+type icrc21_consent_message_request = record {
+    method: text;
+    arg: blob;
+    user_preferences: icrc21_consent_message_spec;
+};
+
+type icrc21_consent_message = variant {
+    GenericDisplayMessage: text;
+    LineDisplayMessage: record {
+        pages: vec record {
+            lines: vec text;
+        };
+    };
+};
+
+type icrc21_consent_info = record {
+    consent_message: icrc21_consent_message;
+    metadata: icrc21_consent_message_metadata;
+};
+
+type icrc21_error_info = record {
+    description: text;
+};
+
+type icrc21_error = variant {
+    UnsupportedCanisterCall: icrc21_error_info;
+    ConsentMessageUnavailable: icrc21_error_info;
+    InsufficientPayment: icrc21_error_info;
+
+    // Any error not covered by the above variants.
+    GenericError: record {
+       error_code: nat;
+       description: text;
+   };
+};
+
+type icrc21_consent_message_response = variant {
+    Ok: icrc21_consent_info;
+    Err: icrc21_error;
+};
+
+// TODO Demergent Labs added this, upstream if possible
+type DecimalsResult = record {
+    decimals: nat32;
+};
+
+// TODO Demergent Labs added this, upstream if possible
+type NameResult = record {
+    name: text;
+};
+
+// TODO Demergent Labs added this, upstream if possible
+type SymbolResult = record {
+    symbol: text;
+};
+
+service: (LedgerCanisterPayload) -> {
+    // Transfers tokens from a subaccount of the caller to the destination address.
+    // The source address is computed from the principal of the caller and the specified subaccount.
+    // When successful, returns the index of the block containing the transaction.
+    transfer : (TransferArgs) -> (TransferResult);
+
+    // Returns the amount of Tokens on the specified account.
+    account_balance : (AccountBalanceArgs) -> (Tokens) query;
+
+    // Returns the account identifier for the given Principal and subaccount.
+    account_identifier : (Account) -> (AccountIdentifier) query;
+
+    // Returns the current transfer_fee.
+    transfer_fee : (TransferFeeArg) -> (TransferFee) query;
+
+    // Queries blocks in the specified range.
+    query_blocks : (GetBlocksArgs) -> (QueryBlocksResponse) query;
+
+    // Queries encoded blocks in the specified range
+    query_encoded_blocks : (GetBlocksArgs) -> (QueryEncodedBlocksResponse) query;
+    
+    // Returns token symbol.
+    symbol : () -> (SymbolResult) query;
+
+    // Returns token name.
+    name : () -> (NameResult) query;
+
+    // Returns token decimals.
+    decimals : () -> (DecimalsResult) query;
+
+    // Returns the existing archive canisters information.
+    archives : () -> (Archives) query;
+
+    send_dfx : (SendArgs) -> (BlockIndex);
+    account_balance_dfx : (AccountBalanceArgsDfx) -> (Tokens) query;
+
+    // The following methods implement the ICRC-1 Token Standard.
+    // https://github.com/dfinity/ICRC-1/tree/main/standards/ICRC-1
+    icrc1_name : () -> (text) query;
+    icrc1_symbol : () -> (text) query;
+    icrc1_decimals : () -> (nat8) query;
+    icrc1_metadata : () -> (vec record { text; Value }) query;
+    icrc1_total_supply : () -> (Icrc1Tokens) query;
+    icrc1_fee : () -> (Icrc1Tokens) query;
+    icrc1_minting_account : () -> (opt Account) query;
+    icrc1_balance_of : (Account) -> (Icrc1Tokens) query;
+    icrc1_transfer : (TransferArg) -> (Icrc1TransferResult);
+    icrc1_supported_standards : () -> (vec record { name : text; url : text }) query;
+    icrc2_approve : (ApproveArgs) -> (ApproveResult);
+    icrc2_allowance : (AllowanceArgs) -> (Allowance) query;
+    icrc2_transfer_from : (TransferFromArgs) -> (TransferFromResult);
+
+    icrc21_canister_call_consent_message: (icrc21_consent_message_request) -> (icrc21_consent_message_response);
+    icrc10_supported_standards : () -> (vec record { name : text; url : text }) query;
+}
diff --git a/canisters/icrc/errors.ts b/canisters/icrc/errors.ts
deleted file mode 100644
index df818cd3ad..0000000000
--- a/canisters/icrc/errors.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-import { IDL } from '../../src/lib/stable';
-
-export const BadFee = IDL.Record({
-    expected_fee: IDL.Nat
-});
-export type BadFee = {
-    expected_fee: bigint;
-};
-
-export const BadBurn = IDL.Record({
-    min_burn_amount: IDL.Nat
-});
-export type BadBurn = {
-    min_burn_amount: bigint;
-};
-
-export const InsufficientFunds = IDL.Record({
-    balance: IDL.Nat
-});
-export type InsufficientFunds = {
-    balance: bigint;
-};
-
-export const Duplicate = IDL.Record({
-    duplicate_of: IDL.Nat
-});
-export type Duplicate = {
-    duplicate_of: bigint;
-};
-
-export const GenericError = IDL.Record({
-    error_code: IDL.Nat,
-    message: IDL.Text
-});
-export type GenericError = {
-    error_code: bigint;
-    message: string;
-};
diff --git a/canisters/icrc/icrc.did b/canisters/icrc/icrc.did
deleted file mode 100644
index b64bd5ff4e..0000000000
--- a/canisters/icrc/icrc.did
+++ /dev/null
@@ -1,311 +0,0 @@
-// Combined from https://github.com/dfinity/ICRC-1/blob/main/standards/ICRC-1/ICRC-1.did
-// and https://github.com/dfinity/ICRC-1/blob/main/standards/ICRC-2/ICRC-2.did
-
-// Number of nanoseconds since the UNIX epoch in UTC timezone.
-type Timestamp = nat64;
-
-// Number of nanoseconds between two [Timestamp]s.
-type Duration = nat64;
-
-type Subaccount = blob;
-
-type Account = record {
-    owner : principal;
-    subaccount : opt Subaccount;
-};
-
-type TransferArgs = record {
-    from_subaccount : opt Subaccount;
-    to : Account;
-    amount : nat;
-    fee : opt nat;
-    memo : opt blob;
-    created_at_time : opt Timestamp;
-};
-
-type TransferError = variant {
-    BadFee : record { expected_fee : nat };
-    BadBurn : record { min_burn_amount : nat };
-    InsufficientFunds : record { balance : nat };
-    TooOld;
-    CreatedInFuture: record { ledger_time : Timestamp };
-    Duplicate : record { duplicate_of : nat };
-    TemporarilyUnavailable;
-    GenericError : record { error_code : nat; message : text };
-};
-
-type Value = variant {
-    Nat : nat;
-    Int : int;
-    Text : text;
-    Blob : blob;
-};
-
-type ApproveArgs = record {
-    from_subaccount : opt blob;
-    spender : Account;
-    amount : nat;
-    expected_allowance : opt nat;
-    expires_at : opt nat64;
-    fee : opt nat;
-    memo : opt blob;
-    created_at_time : opt nat64;
-};
-
-type ApproveError = variant {
-    BadFee : record { expected_fee : nat };
-    InsufficientFunds : record { balance : nat };
-    AllowanceChanged : record { current_allowance : nat };
-    Expired : record { ledger_time : nat64 };
-    TooOld;
-    CreatedInFuture: record { ledger_time : nat64 };
-    Duplicate : record { duplicate_of : nat };
-    TemporarilyUnavailable;
-    GenericError : record { error_code : nat; message : text };
-};
-
-type TransferFromArgs = record {
-    spender_subaccount : opt blob;
-    from : Account;
-    to : Account;
-    amount : nat;
-    fee : opt nat;
-    memo : opt blob;
-    created_at_time : opt nat64;
-};
-
-type TransferFromError = variant {
-    BadFee : record { expected_fee : nat };
-    BadBurn : record { min_burn_amount : nat };
-    InsufficientFunds : record { balance : nat };
-    InsufficientAllowance : record { allowance : nat };
-    TooOld;
-    CreatedInFuture: record { ledger_time : nat64 };
-    Duplicate : record { duplicate_of : nat };
-    TemporarilyUnavailable;
-    GenericError : record { error_code : nat; message : text };
-};
-
-type AllowanceArgs = record {
-    account : Account;
-    spender : Account;
-};
-
-service : {
-    icrc1_metadata : () -> (vec record { text; Value; }) query;
-    icrc1_name : () -> (text) query;
-    icrc1_symbol : () -> (text) query;
-    icrc1_decimals : () -> (nat8) query;
-    icrc1_fee : () -> (nat) query;
-    icrc1_total_supply : () -> (nat) query;
-    icrc1_minting_account : () -> (opt Account) query;
-    icrc1_balance_of : (Account) -> (nat) query;
-    icrc1_transfer : (TransferArgs) -> (variant { Ok : nat; Err : TransferError });
-    icrc1_supported_standards : () -> (vec record { name : text; url : text }) query;
-
-    icrc2_approve : (ApproveArgs) -> (variant { Ok : nat; Err : ApproveError });
-    icrc2_transfer_from : (TransferFromArgs) -> (variant { Ok : nat; Err : TransferFromError });
-    icrc2_allowance : (AllowanceArgs) -> (record { allowance : nat; expires_at : opt nat64 }) query;
-}
-
-// Apache License
-// Version 2.0, January 2004
-// http://www.apache.org/licenses/
-
-// TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-// 1. Definitions.
-
-// "License" shall mean the terms and conditions for use, reproduction,
-// and distribution as defined by Sections 1 through 9 of this document.
-
-// "Licensor" shall mean the copyright owner or entity authorized by
-// the copyright owner that is granting the License.
-
-// "Legal Entity" shall mean the union of the acting entity and all
-// other entities that control, are controlled by, or are under common
-// control with that entity. For the purposes of this definition,
-// "control" means (i) the power, direct or indirect, to cause the
-// direction or management of such entity, whether by contract or
-// otherwise, or (ii) ownership of fifty percent (50%) or more of the
-// outstanding shares, or (iii) beneficial ownership of such entity.
-
-// "You" (or "Your") shall mean an individual or Legal Entity
-// exercising permissions granted by this License.
-
-// "Source" form shall mean the preferred form for making modifications,
-// including but not limited to software source code, documentation
-// source, and configuration files.
-
-// "Object" form shall mean any form resulting from mechanical
-// transformation or translation of a Source form, including but
-// not limited to compiled object code, generated documentation,
-// and conversions to other media types.
-
-// "Work" shall mean the work of authorship, whether in Source or
-// Object form, made available under the License, as indicated by a
-// copyright notice that is included in or attached to the work
-// (an example is provided in the Appendix below).
-
-// "Derivative Works" shall mean any work, whether in Source or Object
-// form, that is based on (or derived from) the Work and for which the
-// editorial revisions, annotations, elaborations, or other modifications
-// represent, as a whole, an original work of authorship. For the purposes
-// of this License, Derivative Works shall not include works that remain
-// separable from, or merely link (or bind by name) to the interfaces of,
-// the Work and Derivative Works thereof.
-
-// "Contribution" shall mean any work of authorship, including
-// the original version of the Work and any modifications or additions
-// to that Work or Derivative Works thereof, that is intentionally
-// submitted to Licensor for inclusion in the Work by the copyright owner
-// or by an individual or Legal Entity authorized to submit on behalf of
-// the copyright owner. For the purposes of this definition, "submitted"
-// means any form of electronic, verbal, or written communication sent
-// to the Licensor or its representatives, including but not limited to
-// communication on electronic mailing lists, source code control systems,
-// and issue tracking systems that are managed by, or on behalf of, the
-// Licensor for the purpose of discussing and improving the Work, but
-// excluding communication that is conspicuously marked or otherwise
-// designated in writing by the copyright owner as "Not a Contribution."
-
-// "Contributor" shall mean Licensor and any individual or Legal Entity
-// on behalf of whom a Contribution has been received by Licensor and
-// subsequently incorporated within the Work.
-
-// 2. Grant of Copyright License. Subject to the terms and conditions of
-// this License, each Contributor hereby grants to You a perpetual,
-// worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-// copyright license to reproduce, prepare Derivative Works of,
-// publicly display, publicly perform, sublicense, and distribute the
-// Work and such Derivative Works in Source or Object form.
-
-// 3. Grant of Patent License. Subject to the terms and conditions of
-// this License, each Contributor hereby grants to You a perpetual,
-// worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-// (except as stated in this section) patent license to make, have made,
-// use, offer to sell, sell, import, and otherwise transfer the Work,
-// where such license applies only to those patent claims licensable
-// by such Contributor that are necessarily infringed by their
-// Contribution(s) alone or by combination of their Contribution(s)
-// with the Work to which such Contribution(s) was submitted. If You
-// institute patent litigation against any entity (including a
-// cross-claim or counterclaim in a lawsuit) alleging that the Work
-// or a Contribution incorporated within the Work constitutes direct
-// or contributory patent infringement, then any patent licenses
-// granted to You under this License for that Work shall terminate
-// as of the date such litigation is filed.
-
-// 4. Redistribution. You may reproduce and distribute copies of the
-// Work or Derivative Works thereof in any medium, with or without
-// modifications, and in Source or Object form, provided that You
-// meet the following conditions:
-
-// (a) You must give any other recipients of the Work or
-// Derivative Works a copy of this License; and
-
-// (b) You must cause any modified files to carry prominent notices
-// stating that You changed the files; and
-
-// (c) You must retain, in the Source form of any Derivative Works
-// that You distribute, all copyright, patent, trademark, and
-// attribution notices from the Source form of the Work,
-// excluding those notices that do not pertain to any part of
-// the Derivative Works; and
-
-// (d) If the Work includes a "NOTICE" text file as part of its
-// distribution, then any Derivative Works that You distribute must
-// include a readable copy of the attribution notices contained
-// within such NOTICE file, excluding those notices that do not
-// pertain to any part of the Derivative Works, in at least one
-// of the following places: within a NOTICE text file distributed
-// as part of the Derivative Works; within the Source form or
-// documentation, if provided along with the Derivative Works; or,
-// within a display generated by the Derivative Works, if and
-// wherever such third-party notices normally appear. The contents
-// of the NOTICE file are for informational purposes only and
-// do not modify the License. You may add Your own attribution
-// notices within Derivative Works that You distribute, alongside
-// or as an addendum to the NOTICE text from the Work, provided
-// that such additional attribution notices cannot be construed
-// as modifying the License.
-
-// You may add Your own copyright statement to Your modifications and
-// may provide additional or different license terms and conditions
-// for use, reproduction, or distribution of Your modifications, or
-// for any such Derivative Works as a whole, provided Your use,
-// reproduction, and distribution of the Work otherwise complies with
-// the conditions stated in this License.
-
-// 5. Submission of Contributions. Unless You explicitly state otherwise,
-// any Contribution intentionally submitted for inclusion in the Work
-// by You to the Licensor shall be under the terms and conditions of
-// this License, without any additional terms or conditions.
-// Notwithstanding the above, nothing herein shall supersede or modify
-// the terms of any separate license agreement you may have executed
-// with Licensor regarding such Contributions.
-
-// 6. Trademarks. This License does not grant permission to use the trade
-// names, trademarks, service marks, or product names of the Licensor,
-// except as required for reasonable and customary use in describing the
-// origin of the Work and reproducing the content of the NOTICE file.
-
-// 7. Disclaimer of Warranty. Unless required by applicable law or
-// agreed to in writing, Licensor provides the Work (and each
-// Contributor provides its Contributions) on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied, including, without limitation, any warranties or conditions
-// of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-// PARTICULAR PURPOSE. You are solely responsible for determining the
-// appropriateness of using or redistributing the Work and assume any
-// risks associated with Your exercise of permissions under this License.
-
-// 8. Limitation of Liability. In no event and under no legal theory,
-// whether in tort (including negligence), contract, or otherwise,
-// unless required by applicable law (such as deliberate and grossly
-// negligent acts) or agreed to in writing, shall any Contributor be
-// liable to You for damages, including any direct, indirect, special,
-// incidental, or consequential damages of any character arising as a
-// result of this License or out of the use or inability to use the
-// Work (including but not limited to damages for loss of goodwill,
-// work stoppage, computer failure or malfunction, or any and all
-// other commercial damages or losses), even if such Contributor
-// has been advised of the possibility of such damages.
-
-// 9. Accepting Warranty or Additional Liability. While redistributing
-// the Work or Derivative Works thereof, You may choose to offer,
-// and charge a fee for, acceptance of support, warranty, indemnity,
-// or other liability obligations and/or rights consistent with this
-// License. However, in accepting such obligations, You may act only
-// on Your own behalf and on Your sole responsibility, not on behalf
-// of any other Contributor, and only if You agree to indemnify,
-// defend, and hold each Contributor harmless for any liability
-// incurred by, or claims asserted against, such Contributor by reason
-// of your accepting any such warranty or additional liability.
-
-// END OF TERMS AND CONDITIONS
-
-// APPENDIX: How to apply the Apache License to your work.
-
-// To apply the Apache License to your work, attach the following
-// boilerplate notice, with the fields enclosed by brackets "[]"
-// replaced with your own identifying information. (Don't include
-// the brackets!)  The text should be enclosed in the appropriate
-// comment syntax for the file format. We also recommend that a
-// file or class name and description of purpose be included on the
-// same "printed page" as the copyright notice for easier
-// identification within third-party archives.
-
-// Copyright 2023 DFINITY Foundation
-
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-
-// http://www.apache.org/licenses/LICENSE-2.0
-
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
diff --git a/canisters/icrc/icrc_1.ts b/canisters/icrc/icrc_1.ts
deleted file mode 100644
index c5886e6adf..0000000000
--- a/canisters/icrc/icrc_1.ts
+++ /dev/null
@@ -1,110 +0,0 @@
-import { IDL, Principal } from '../../src/lib/stable';
-import {
-    BadBurn,
-    BadFee,
-    Duplicate,
-    GenericError,
-    InsufficientFunds
-} from './errors';
-
-// Number of nanoseconds since the UNIX epoch in UTC timezone.
-export const Timestamp = IDL.Nat64;
-export type Timestamp = bigint;
-
-export const Subaccount = IDL.Vec(IDL.Nat8);
-export type Subaccount = Uint8Array;
-
-export const Account = IDL.Record({
-    owner: IDL.Principal,
-    subaccount: IDL.Opt(Subaccount)
-});
-export type Account = {
-    owner: Principal;
-    subaccount: [Subaccount] | [];
-};
-
-export const TransferArgs = IDL.Record({
-    from_subaccount: IDL.Opt(Subaccount),
-    to: Account,
-    amount: IDL.Nat,
-    fee: IDL.Opt(IDL.Nat),
-    memo: IDL.Opt(IDL.Vec(IDL.Nat8)),
-    created_at_time: IDL.Opt(Timestamp)
-});
-export type TransferArgs = {
-    from_subaccount: [Subaccount] | [];
-    to: Account;
-    amount: bigint;
-    fee: [bigint] | [];
-    memo: [Uint8Array] | [];
-    created_at_time: [Timestamp] | [];
-};
-
-export const CreatedInFuture = IDL.Record({
-    ledger_time: Timestamp
-});
-export type CreatedInFuture = {
-    ledger_time: Timestamp;
-};
-
-export const TransferError = IDL.Variant({
-    BadFee,
-    BadBurn,
-    InsufficientFunds,
-    TooOld: IDL.Null,
-    CreatedInFuture: CreatedInFuture,
-    Duplicate: Duplicate,
-    TemporarilyUnavailable: IDL.Null,
-    GenericError: GenericError
-});
-export type TransferError =
-    | {
-          BadFee: BadFee;
-      }
-    | {
-          BadBurn: BadBurn;
-      }
-    | {
-          InsufficientFunds: InsufficientFunds;
-      }
-    | {
-          TooOld: null;
-      }
-    | {
-          CreatedInFuture: CreatedInFuture;
-      }
-    | {
-          Duplicate: Duplicate;
-      }
-    | {
-          TemporarilyUnavailable: null;
-      }
-    | {
-          GenericError: GenericError;
-      };
-
-export const TransferResult = IDL.Variant({
-    Ok: IDL.Nat,
-    Err: TransferError
-});
-export type TransferResult = { Ok: bigint } | { Err: TransferError };
-
-export const Value = IDL.Variant({
-    Nat: IDL.Nat,
-    Int: IDL.Int,
-    Text: IDL.Text,
-    Blob: IDL.Vec(IDL.Nat8)
-});
-export type Value =
-    | {
-          Nat: bigint;
-      }
-    | {
-          Int: bigint;
-      }
-    | {
-          Text: string;
-      }
-    | {
-          Blob: Uint8Array;
-      };
diff --git a/canisters/icrc/icrc_2.ts b/canisters/icrc/icrc_2.ts
deleted file mode 100644
index 18324d4d81..0000000000
--- a/canisters/icrc/icrc_2.ts
+++ /dev/null
@@ -1,192 +0,0 @@
-import { IDL } from '../../src/lib/stable';
-import {
-    BadBurn,
-    BadFee,
-    Duplicate,
-    GenericError,
-    InsufficientFunds
-} from './errors';
-import { Account, CreatedInFuture } from './icrc_1';
-
-export const ApproveArgs = IDL.Record({
-    from_subaccount: IDL.Opt(IDL.Vec(IDL.Nat8)),
-    spender: Account,
-    amount: IDL.Nat,
-    expected_allowance: IDL.Opt(IDL.Nat),
-    expires_at: IDL.Opt(IDL.Nat64),
-    fee: IDL.Opt(IDL.Nat),
-    memo: IDL.Opt(IDL.Vec(IDL.Nat8)),
-    created_at_time: IDL.Opt(IDL.Nat64)
-});
-export type ApproveArgs = {
-    from_subaccount: [Uint8Array] | [];
-    spender: Account;
-    amount: bigint;
-    expected_allowance: [bigint] | [];
-    expires_at: [bigint] | [];
-    fee: [bigint] | [];
-    memo: [Uint8Array] | [];
-    created_at_time: [bigint] | [];
-};
-
-export const AllowanceChanged = IDL.Record({
-    current_allowance: IDL.Nat
-});
-export type AllowanceChanged = {
-    current_allowance: bigint;
-};
-
-export const Expired = IDL.Record({
-    ledger_time: IDL.Nat64
-});
-export type Expired = {
-    ledger_time: bigint;
-};
-
-export const InsufficientAllowance = IDL.Record({
-    allowance: IDL.Nat
-});
-export type InsufficientAllowance = {
-    allowance: bigint;
-};
-
-export const ApproveError = IDL.Variant({
-    BadFee,
-    InsufficientFunds,
-    AllowanceChanged,
-    Expired,
-    TooOld: IDL.Null,
-    CreatedInFuture,
-    Duplicate,
-    TemporarilyUnavailable: IDL.Null,
-    GenericError: GenericError
-});
-export type ApproveError =
-    | {
-          BadFee: BadFee;
-      }
-    | {
-          InsufficientFunds: InsufficientFunds;
-      }
-    | {
-          AllowanceChanged: AllowanceChanged;
-      }
-    | {
-          Expired: Expired;
-      }
-    | {
-          TooOld: null;
-      }
-    | {
-          CreatedInFuture: CreatedInFuture;
-      }
-    | {
-          Duplicate: Duplicate;
-      }
-    | {
-          TemporarilyUnavailable: null;
-      }
-    | {
-          GenericError: GenericError;
-      };
-
-export const TransferFromArgs = IDL.Record({
-    spender_subaccount: IDL.Opt(IDL.Vec(IDL.Nat8)),
-    from: Account,
-    to: Account,
-    amount: IDL.Nat,
-    fee: IDL.Opt(IDL.Nat),
-    memo: IDL.Opt(IDL.Vec(IDL.Nat8)),
-    created_at_time: IDL.Opt(IDL.Nat64)
-});
-export type TransferFromArgs = {
-    spender_subaccount: [Uint8Array] | [];
-    from: Account;
-    to: Account;
-    amount: bigint;
-    fee: [bigint] | [];
-    memo: [Uint8Array] | [];
-    created_at_time: [bigint] | [];
-};
-
-export const TransferFromError = IDL.Variant({
-    BadFee,
-    BadBurn,
-    InsufficientFunds,
-    InsufficientAllowance,
-    TooOld: IDL.Null,
-    CreatedInFuture,
-    Duplicate,
-    TemporarilyUnavailable: IDL.Null,
-    GenericError
-});
-export type TransferFromError =
-    | {
-          BadFee: BadFee;
-      }
-    | {
-          BadBurn: BadBurn;
-      }
-    | {
-          InsufficientFunds: InsufficientFunds;
-      }
-    | {
-          InsufficientAllowance: InsufficientAllowance;
-      }
-    | {
-          TooOld: null;
-      }
-    | {
-          CreatedInFuture: CreatedInFuture;
-      }
-    | {
-          Duplicate: Duplicate;
-      }
-    | {
-          TemporarilyUnavailable: null;
-      }
-    | {
-          GenericError: GenericError;
-      };
-
-export const AllowanceArgs = IDL.Record({
-    account: Account,
-    spender: Account
-});
-export type AllowanceArgs = {
-    account: Account;
-    spender: Account;
-};
-
-export const ApproveResult = IDL.Variant({
-    Ok: IDL.Nat,
-    Err: ApproveError
-});
-export type ApproveResult =
-    | {
-          Ok: bigint;
-      }
-    | {
-          Err: ApproveError;
-      };
-
-export const TransferFromResult = IDL.Variant({
-    Ok: IDL.Nat,
-    Err: TransferFromError
-});
-export type TransferFromResult =
-    | {
-          Ok: bigint;
-      }
-    | {
-          Err: TransferFromError;
-      };
-
-export const AllowanceResult = IDL.Record({
-    allowance: IDL.Nat,
-    expires_at: IDL.Opt(IDL.Nat64)
-});
-export type AllowanceResult = {
-    allowance: bigint;
-    expires_at: [bigint] | [];
-};
diff --git a/canisters/icrc/index.ts b/canisters/icrc/index.ts
deleted file mode 100644
index 0ad69523ef..0000000000
--- a/canisters/icrc/index.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-import { IDL } from '../../src/lib/stable';
-import { Account, TransferArgs, TransferResult, Value } from './icrc_1';
-import {
-    AllowanceArgs,
-    AllowanceResult,
-    ApproveArgs,
-    ApproveResult,
-    TransferFromArgs,
-    TransferFromResult
-} from './icrc_2';
-
-export const SupportedStandard = IDL.Record({
-    name: IDL.Text,
-    url: IDL.Text
-});
-export type SupportedStandard = {
-    name: string;
-    url: string;
-};
-
-export const ICRC = IDL.Service({
-    icrc1_metadata: IDL.Func(
-        [],
-        [IDL.Vec(IDL.Tuple(IDL.Text, Value))],
-        ['query']
-    ),
-    icrc1_name: IDL.Func([], [IDL.Text], ['query']),
-    icrc1_symbol: IDL.Func([], [IDL.Text], ['query']),
-    icrc1_decimals: IDL.Func([], [IDL.Nat8], ['query']),
-    icrc1_fee: IDL.Func([], [IDL.Nat], ['query']),
-    icrc1_total_supply: IDL.Func([], [IDL.Nat], ['query']),
-    icrc1_minting_account: IDL.Func([], [IDL.Opt(Account)], ['query']),
-    icrc1_balance_of: IDL.Func([Account], [IDL.Nat], ['query']),
-    icrc1_transfer: IDL.Func([TransferArgs], [TransferResult]),
-    icrc1_supported_standards: IDL.Func(
-        [],
-        [IDL.Vec(SupportedStandard)],
-        ['query']
-    ),
-    icrc2_approve: IDL.Func([ApproveArgs], [ApproveResult]),
-    icrc2_transfer_from: IDL.Func([TransferFromArgs], [TransferFromResult]),
-    icrc2_allowance: IDL.Func([AllowanceArgs], [AllowanceResult], ['query'])
-});
-
-export * from './icrc_1';
-export * from './icrc_2';
diff --git a/canisters/icrc_1/ICRC-1.did b/canisters/icrc_1/ICRC-1.did
new file mode 100644
index 0000000000..989028bb8e
--- /dev/null
+++ b/canisters/icrc_1/ICRC-1.did
@@ -0,0 +1,63 @@
+// Taken from: https://github.com/dfinity/ICRC-1/blob/effeeaa89d8dd75ce3b2215b9c36eed98dafb7a8/standards/ICRC-1/ICRC-1.did
+
+// Number of nanoseconds since the UNIX epoch in UTC timezone.
+type Timestamp = nat64;
+
+// Number of nanoseconds between two [Timestamp]s.
+type Duration = nat64;
+
+type Subaccount = blob;
+
+type Account = record {
+    owner : principal;
+    subaccount : opt Subaccount;
+};
+
+type TransferArgs = record {
+    from_subaccount : opt Subaccount;
+    to : Account;
+    amount : nat;
+    fee : opt nat;
+    memo : opt blob;
+    created_at_time : opt Timestamp;
+};
+
+// TODO added by Demergent Labs, would be nice to upstream or automate
+type TransferResult = variant { Ok : nat; Err : TransferError };
+
+type TransferError = variant {
+    BadFee : record { expected_fee : nat };
+    BadBurn : record { min_burn_amount : nat };
+    InsufficientFunds : record { balance : nat };
+    TooOld;
+    CreatedInFuture: record { ledger_time : Timestamp };
+    Duplicate : record { duplicate_of : nat };
+    TemporarilyUnavailable;
+    GenericError : record { error_code : nat; message : text };
+};
+
+type Value = variant {
+    Nat : nat;
+    Int : int;
+    Text : text;
+    Blob : blob;
+};
+
+// TODO added by Demergent Labs, would be nice to upstream or automate
+type Metadatum = record { text; Value; };
+
+// TODO added by Demergent Labs, would be nice to upstream or automate
+type SupportedStandard = record { name : text; url : text };
+
+service : {
+    icrc1_metadata : () -> (vec Metadatum) query;
+    icrc1_name : () -> (text) query;
+    icrc1_symbol : () -> (text) query;
+    icrc1_decimals : () -> (nat8) query;
+    icrc1_fee : () -> (nat) query;
+    icrc1_total_supply : () -> (nat) query;
+    icrc1_minting_account : () -> (opt Account) query;
+    icrc1_balance_of : (Account) -> (nat) query;
+    icrc1_transfer : (TransferArgs) -> (TransferResult);
+    icrc1_supported_standards : () -> (vec SupportedStandard) query;
+}
diff --git a/canisters/icrc_1/LICENSE b/canisters/icrc_1/LICENSE
new file mode 100644
index 0000000000..d645695673
--- /dev/null
+++ b/canisters/icrc_1/LICENSE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/canisters/icrc_1/index.ts b/canisters/icrc_1/index.ts
new file mode 100644
index 0000000000..7755df0237
--- /dev/null
+++ b/canisters/icrc_1/index.ts
@@ -0,0 +1,150 @@
+import { ActorMethod } from '@dfinity/agent';
+import { IDL } from '@dfinity/candid';
+import { Principal } from '@dfinity/principal';
+export interface Account {
+    owner: Principal;
+    subaccount: [] | [Subaccount];
+}
+export type Duration = bigint;
+export type Metadatum = [string, Value];
+export type Subaccount = Uint8Array | number[];
+export interface SupportedStandard {
+    url: string;
+    name: string;
+}
+export type Timestamp = bigint;
+export interface TransferArgs {
+    to: Account;
+    fee: [] | [bigint];
+    memo: [] | [Uint8Array | number[]];
+    from_subaccount: [] | [Subaccount];
+    created_at_time: [] | [Timestamp];
+    amount: bigint;
+}
+export type TransferError =
+    | {
+          GenericError: { message: string; error_code: bigint };
+      }
+    | { TemporarilyUnavailable: null }
+    | { BadBurn: { min_burn_amount: bigint } }
+    | { Duplicate: { duplicate_of: bigint } }
+    | { BadFee: { expected_fee: bigint } }
+    | { CreatedInFuture: { ledger_time: Timestamp } }
+    | { TooOld: null }
+    | { InsufficientFunds: { balance: bigint } };
+export type TransferResult = { Ok: bigint } | { Err: TransferError };
+export type Value =
+    | { Int: bigint }
+    | { Nat: bigint }
+    | { Blob: Uint8Array | number[] }
+    | { Text: string };
+export interface _SERVICE {
+    icrc1_balance_of: ActorMethod<[Account], bigint>;
+    icrc1_decimals: ActorMethod<[], number>;
+    icrc1_fee: ActorMethod<[], bigint>;
+    icrc1_metadata: ActorMethod<[], Array<Metadatum>>;
+    icrc1_minting_account: ActorMethod<[], [] | [Account]>;
+    icrc1_name: ActorMethod<[], string>;
+    icrc1_supported_standards: ActorMethod<[], Array<SupportedStandard>>;
+    icrc1_symbol: ActorMethod<[], string>;
+    icrc1_total_supply: ActorMethod<[], bigint>;
+    icrc1_transfer: ActorMethod<[TransferArgs], TransferResult>;
+}
+export type idlFactory = IDL.InterfaceFactory;
+export type init = (args: { IDL: typeof IDL }) => IDL.Type[];
+export const Subaccount = IDL.Vec(IDL.Nat8);
+export const Account = IDL.Record({
+    owner: IDL.Principal,
+    subaccount: IDL.Opt(Subaccount)
+});
+export const Value = IDL.Variant({
+    Int: IDL.Int,
+    Nat: IDL.Nat,
+    Blob: IDL.Vec(IDL.Nat8),
+    Text: IDL.Text
+});
+export const Metadatum = IDL.Tuple(IDL.Text, Value);
+export const SupportedStandard = IDL.Record({
+    url: IDL.Text,
+    name: IDL.Text
+});
+export const Timestamp = IDL.Nat64;
+export const TransferArgs = IDL.Record({
+    to: Account,
+    fee: IDL.Opt(IDL.Nat),
+    memo: IDL.Opt(IDL.Vec(IDL.Nat8)),
+    from_subaccount: IDL.Opt(Subaccount),
+    created_at_time: IDL.Opt(Timestamp),
+    amount: IDL.Nat
+});
+export const TransferError = IDL.Variant({
+    GenericError: IDL.Record({ message: IDL.Text, error_code: IDL.Nat }),
+    TemporarilyUnavailable: IDL.Null,
+    BadBurn: IDL.Record({ min_burn_amount: IDL.Nat }),
+    Duplicate: IDL.Record({ duplicate_of: IDL.Nat }),
+    BadFee: IDL.Record({ expected_fee: IDL.Nat }),
+    CreatedInFuture: IDL.Record({ ledger_time: Timestamp }),
+    TooOld: IDL.Null,
+    InsufficientFunds: IDL.Record({ balance: IDL.Nat })
+});
+export const TransferResult = IDL.Variant({
+    Ok: IDL.Nat,
+    Err: TransferError
+});
+export const idlFactory: idlFactory = ({ IDL }) => {
+    const Subaccount = IDL.Vec(IDL.Nat8);
+    const Account = IDL.Record({
+        owner: IDL.Principal,
+        subaccount: IDL.Opt(Subaccount)
+    });
+    const Value = IDL.Variant({
+        Int: IDL.Int,
+        Nat: IDL.Nat,
+        Blob: IDL.Vec(IDL.Nat8),
+        Text: IDL.Text
+    });
+    const Metadatum = IDL.Tuple(IDL.Text, Value);
+    const SupportedStandard = IDL.Record({ url: IDL.Text, name: IDL.Text });
+    const Timestamp = IDL.Nat64;
+    const TransferArgs = IDL.Record({
+        to: Account,
+        fee: IDL.Opt(IDL.Nat),
+        memo: IDL.Opt(IDL.Vec(IDL.Nat8)),
+        from_subaccount: IDL.Opt(Subaccount),
+        created_at_time: IDL.Opt(Timestamp),
+        amount: IDL.Nat
+    });
+    const TransferError = IDL.Variant({
+        GenericError: IDL.Record({
+            message: IDL.Text,
+            error_code: IDL.Nat
+        }),
+        TemporarilyUnavailable: IDL.Null,
+        BadBurn: IDL.Record({ min_burn_amount: IDL.Nat }),
+        Duplicate: IDL.Record({ duplicate_of: IDL.Nat }),
+        BadFee: IDL.Record({ expected_fee: IDL.Nat }),
+        CreatedInFuture: IDL.Record({ ledger_time: Timestamp }),
+        TooOld: IDL.Null,
+        InsufficientFunds: IDL.Record({ balance: IDL.Nat })
+    });
+    const TransferResult = IDL.Variant({ Ok: IDL.Nat, Err: TransferError });
+    return IDL.Service({
+        icrc1_balance_of: IDL.Func([Account], [IDL.Nat], ['query']),
+        icrc1_decimals: IDL.Func([], [IDL.Nat8], ['query']),
+        icrc1_fee: IDL.Func([], [IDL.Nat], ['query']),
+        icrc1_metadata: IDL.Func([], [IDL.Vec(Metadatum)], ['query']),
+        icrc1_minting_account: IDL.Func([], [IDL.Opt(Account)], ['query']),
+        icrc1_name: IDL.Func([], [IDL.Text], ['query']),
+        icrc1_supported_standards: IDL.Func(
+            [],
+            [IDL.Vec(SupportedStandard)],
+            ['query']
+        ),
+        icrc1_symbol: IDL.Func([], [IDL.Text], ['query']),
+        icrc1_total_supply: IDL.Func([], [IDL.Nat], ['query']),
+        icrc1_transfer: IDL.Func([TransferArgs], [TransferResult], [])
+    });
+};
+export const init: init = () => {
+    return [];
+};
diff --git a/canisters/icrc_10/ICRC-10.did b/canisters/icrc_10/ICRC-10.did
new file mode 100644
index 0000000000..d9a1c6a7c2
--- /dev/null
+++ b/canisters/icrc_10/ICRC-10.did
@@ -0,0 +1,8 @@
+// Taken from: https://github.com/dfinity/ICRC/blob/946bd6518acb2aafd1828b93dfde9e47657fd758/ICRCs/ICRC-10/ICRC-10.did
+
+type SupportedStandard = record { name : text; url : text; };
+type SupportedStandardsResponse = vec SupportedStandard;
+
+service : {
+  icrc10_supported_standards : () -> (SupportedStandardsResponse) query;
+}
diff --git a/canisters/icrc_10/LICENSE b/canisters/icrc_10/LICENSE
new file mode 100644
index 0000000000..d645695673
--- /dev/null
+++ b/canisters/icrc_10/LICENSE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/canisters/icrc_10/index.ts b/canisters/icrc_10/index.ts
new file mode 100644
index 0000000000..16496d6777
--- /dev/null
+++ b/canisters/icrc_10/index.ts
@@ -0,0 +1,31 @@
+import { ActorMethod } from '@dfinity/agent';
+import { IDL } from '@dfinity/candid';
+export interface SupportedStandard {
+    url: string;
+    name: string;
+}
+export type SupportedStandardsResponse = Array<SupportedStandard>;
+export interface _SERVICE {
+    icrc10_supported_standards: ActorMethod<[], SupportedStandardsResponse>;
+}
+export type idlFactory = IDL.InterfaceFactory;
+export type init = (args: { IDL: typeof IDL }) => IDL.Type[];
+export const SupportedStandard = IDL.Record({
+    url: IDL.Text,
+    name: IDL.Text
+});
+export const SupportedStandardsResponse = IDL.Vec(SupportedStandard);
+export const idlFactory: idlFactory = ({ IDL }) => {
+    const SupportedStandard = IDL.Record({ url: IDL.Text, name: IDL.Text });
+    const SupportedStandardsResponse = IDL.Vec(SupportedStandard);
+    return IDL.Service({
+        icrc10_supported_standards: IDL.Func(
+            [],
+            [SupportedStandardsResponse],
+            ['query']
+        )
+    });
+};
+export const init: init = () => {
+    return [];
+};
diff --git a/canisters/icrc_2/ICRC-2.did b/canisters/icrc_2/ICRC-2.did
new file mode 100644
index 0000000000..8aae190f5e
--- /dev/null
+++ b/canisters/icrc_2/ICRC-2.did
@@ -0,0 +1,76 @@
+// Taken from: https://github.com/dfinity/ICRC-1/blob/effeeaa89d8dd75ce3b2215b9c36eed98dafb7a8/standards/ICRC-2/ICRC-2.did
+
+type Account = record {
+    owner : principal;
+    subaccount : opt blob;
+};
+
+type ApproveArgs = record {
+    from_subaccount : opt blob;
+    spender : Account;
+    amount : nat;
+    expected_allowance : opt nat;
+    expires_at : opt nat64;
+    fee : opt nat;
+    memo : opt blob;
+    created_at_time : opt nat64;
+};
+
+// TODO added by Demergent Labs, would be nice to upstream or automate
+type ApproveResult = variant { Ok : nat; Err : ApproveError };
+
+type ApproveError = variant {
+    BadFee : record { expected_fee : nat };
+    InsufficientFunds : record { balance : nat };
+    AllowanceChanged : record { current_allowance : nat };
+    Expired : record { ledger_time : nat64 };
+    TooOld;
+    CreatedInFuture: record { ledger_time : nat64 };
+    Duplicate : record { duplicate_of : nat };
+    TemporarilyUnavailable;
+    GenericError : record { error_code : nat; message : text };
+};
+
+type TransferFromArgs = record {
+    spender_subaccount : opt blob;
+    from : Account;
+    to : Account;
+    amount : nat;
+    fee : opt nat;
+    memo : opt blob;
+    created_at_time : opt nat64;
+};
+
+// TODO added by Demergent Labs, would be nice to upstream or automate
+type TransferFromResult = variant { Ok : nat; Err : TransferFromError };
+
+type TransferFromError = variant {
+    BadFee : record { expected_fee : nat };
+    BadBurn : record { min_burn_amount : nat };
+    InsufficientFunds : record { balance : nat };
+    InsufficientAllowance : record { allowance : nat };
+    TooOld;
+    CreatedInFuture: record { ledger_time : nat64 };
+    Duplicate : record { duplicate_of : nat };
+    TemporarilyUnavailable;
+    GenericError : record { error_code : nat; message : text };
+};
+
+type AllowanceArgs = record {
+    account : Account;
+    spender : Account;
+};
+
+// TODO added by Demergent Labs, would be nice to upstream or automate
+type AllowanceResult = record { allowance : nat; expires_at : opt nat64 };
+
+// TODO added by Demergent Labs, would be nice to upstream or automate
+type SupportedStandard = record { name : text; url : text };
+
+service : {
+    icrc1_supported_standards : () -> (vec SupportedStandard) query;
+
+    icrc2_approve : (ApproveArgs) -> (ApproveResult);
+    icrc2_transfer_from : (TransferFromArgs) -> (TransferFromResult);
+    icrc2_allowance : (AllowanceArgs) -> (AllowanceResult) query;
+}
diff --git a/canisters/icrc_2/LICENSE b/canisters/icrc_2/LICENSE
new file mode 100644
index 0000000000..d645695673
--- /dev/null
+++ b/canisters/icrc_2/LICENSE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/canisters/icrc_2/index.ts b/canisters/icrc_2/index.ts
new file mode 100644
index 0000000000..6ad93ad0c2
--- /dev/null
+++ b/canisters/icrc_2/index.ts
@@ -0,0 +1,225 @@
+import { ActorMethod } from '@dfinity/agent';
+import { IDL } from '@dfinity/candid';
+import { Principal } from '@dfinity/principal';
+export interface Account {
+    owner: Principal;
+    subaccount: [] | [Uint8Array | number[]];
+}
+export interface AllowanceArgs {
+    account: Account;
+    spender: Account;
+}
+export interface AllowanceResult {
+    allowance: bigint;
+    expires_at: [] | [bigint];
+}
+export interface ApproveArgs {
+    fee: [] | [bigint];
+    memo: [] | [Uint8Array | number[]];
+    from_subaccount: [] | [Uint8Array | number[]];
+    created_at_time: [] | [bigint];
+    amount: bigint;
+    expected_allowance: [] | [bigint];
+    expires_at: [] | [bigint];
+    spender: Account;
+}
+export type ApproveError =
+    | {
+          GenericError: { message: string; error_code: bigint };
+      }
+    | { TemporarilyUnavailable: null }
+    | { Duplicate: { duplicate_of: bigint } }
+    | { BadFee: { expected_fee: bigint } }
+    | { AllowanceChanged: { current_allowance: bigint } }
+    | { CreatedInFuture: { ledger_time: bigint } }
+    | { TooOld: null }
+    | { Expired: { ledger_time: bigint } }
+    | { InsufficientFunds: { balance: bigint } };
+export type ApproveResult = { Ok: bigint } | { Err: ApproveError };
+export interface SupportedStandard {
+    url: string;
+    name: string;
+}
+export interface TransferFromArgs {
+    to: Account;
+    fee: [] | [bigint];
+    spender_subaccount: [] | [Uint8Array | number[]];
+    from: Account;
+    memo: [] | [Uint8Array | number[]];
+    created_at_time: [] | [bigint];
+    amount: bigint;
+}
+export type TransferFromError =
+    | {
+          GenericError: { message: string; error_code: bigint };
+      }
+    | { TemporarilyUnavailable: null }
+    | { InsufficientAllowance: { allowance: bigint } }
+    | { BadBurn: { min_burn_amount: bigint } }
+    | { Duplicate: { duplicate_of: bigint } }
+    | { BadFee: { expected_fee: bigint } }
+    | { CreatedInFuture: { ledger_time: bigint } }
+    | { TooOld: null }
+    | { InsufficientFunds: { balance: bigint } };
+export type TransferFromResult = { Ok: bigint } | { Err: TransferFromError };
+export interface _SERVICE {
+    icrc1_supported_standards: ActorMethod<[], Array<SupportedStandard>>;
+    icrc2_allowance: ActorMethod<[AllowanceArgs], AllowanceResult>;
+    icrc2_approve: ActorMethod<[ApproveArgs], ApproveResult>;
+    icrc2_transfer_from: ActorMethod<[TransferFromArgs], TransferFromResult>;
+}
+export type idlFactory = IDL.InterfaceFactory;
+export type init = (args: { IDL: typeof IDL }) => IDL.Type[];
+export const SupportedStandard = IDL.Record({
+    url: IDL.Text,
+    name: IDL.Text
+});
+export const Account = IDL.Record({
+    owner: IDL.Principal,
+    subaccount: IDL.Opt(IDL.Vec(IDL.Nat8))
+});
+export const AllowanceArgs = IDL.Record({
+    account: Account,
+    spender: Account
+});
+export const AllowanceResult = IDL.Record({
+    allowance: IDL.Nat,
+    expires_at: IDL.Opt(IDL.Nat64)
+});
+export const ApproveArgs = IDL.Record({
+    fee: IDL.Opt(IDL.Nat),
+    memo: IDL.Opt(IDL.Vec(IDL.Nat8)),
+    from_subaccount: IDL.Opt(IDL.Vec(IDL.Nat8)),
+    created_at_time: IDL.Opt(IDL.Nat64),
+    amount: IDL.Nat,
+    expected_allowance: IDL.Opt(IDL.Nat),
+    expires_at: IDL.Opt(IDL.Nat64),
+    spender: Account
+});
+export const ApproveError = IDL.Variant({
+    GenericError: IDL.Record({ message: IDL.Text, error_code: IDL.Nat }),
+    TemporarilyUnavailable: IDL.Null,
+    Duplicate: IDL.Record({ duplicate_of: IDL.Nat }),
+    BadFee: IDL.Record({ expected_fee: IDL.Nat }),
+    AllowanceChanged: IDL.Record({ current_allowance: IDL.Nat }),
+    CreatedInFuture: IDL.Record({ ledger_time: IDL.Nat64 }),
+    TooOld: IDL.Null,
+    Expired: IDL.Record({ ledger_time: IDL.Nat64 }),
+    InsufficientFunds: IDL.Record({ balance: IDL.Nat })
+});
+export const ApproveResult = IDL.Variant({
+    Ok: IDL.Nat,
+    Err: ApproveError
+});
+export const TransferFromArgs = IDL.Record({
+    to: Account,
+    fee: IDL.Opt(IDL.Nat),
+    spender_subaccount: IDL.Opt(IDL.Vec(IDL.Nat8)),
+    from: Account,
+    memo: IDL.Opt(IDL.Vec(IDL.Nat8)),
+    created_at_time: IDL.Opt(IDL.Nat64),
+    amount: IDL.Nat
+});
+export const TransferFromError = IDL.Variant({
+    GenericError: IDL.Record({ message: IDL.Text, error_code: IDL.Nat }),
+    TemporarilyUnavailable: IDL.Null,
+    InsufficientAllowance: IDL.Record({ allowance: IDL.Nat }),
+    BadBurn: IDL.Record({ min_burn_amount: IDL.Nat }),
+    Duplicate: IDL.Record({ duplicate_of: IDL.Nat }),
+    BadFee: IDL.Record({ expected_fee: IDL.Nat }),
+    CreatedInFuture: IDL.Record({ ledger_time: IDL.Nat64 }),
+    TooOld: IDL.Null,
+    InsufficientFunds: IDL.Record({ balance: IDL.Nat })
+});
+export const TransferFromResult = IDL.Variant({
+    Ok: IDL.Nat,
+    Err: TransferFromError
+});
+export const idlFactory: idlFactory = ({ IDL }) => {
+    const SupportedStandard = IDL.Record({ url: IDL.Text, name: IDL.Text });
+    const Account = IDL.Record({
+        owner: IDL.Principal,
+        subaccount: IDL.Opt(IDL.Vec(IDL.Nat8))
+    });
+    const AllowanceArgs = IDL.Record({
+        account: Account,
+        spender: Account
+    });
+    const AllowanceResult = IDL.Record({
+        allowance: IDL.Nat,
+        expires_at: IDL.Opt(IDL.Nat64)
+    });
+    const ApproveArgs = IDL.Record({
+        fee: IDL.Opt(IDL.Nat),
+        memo: IDL.Opt(IDL.Vec(IDL.Nat8)),
+        from_subaccount: IDL.Opt(IDL.Vec(IDL.Nat8)),
+        created_at_time: IDL.Opt(IDL.Nat64),
+        amount: IDL.Nat,
+        expected_allowance: IDL.Opt(IDL.Nat),
+        expires_at: IDL.Opt(IDL.Nat64),
+        spender: Account
+    });
+    const ApproveError = IDL.Variant({
+        GenericError: IDL.Record({
+            message: IDL.Text,
+            error_code: IDL.Nat
+        }),
+        TemporarilyUnavailable: IDL.Null,
+        Duplicate: IDL.Record({ duplicate_of: IDL.Nat }),
+        BadFee: IDL.Record({ expected_fee: IDL.Nat }),
+        AllowanceChanged: IDL.Record({ current_allowance: IDL.Nat }),
+        CreatedInFuture: IDL.Record({ ledger_time: IDL.Nat64 }),
+        TooOld: IDL.Null,
+        Expired: IDL.Record({ ledger_time: IDL.Nat64 }),
+        InsufficientFunds: IDL.Record({ balance: IDL.Nat })
+    });
+    const ApproveResult = IDL.Variant({ Ok: IDL.Nat, Err: ApproveError });
+    const TransferFromArgs = IDL.Record({
+        to: Account,
+        fee: IDL.Opt(IDL.Nat),
+        spender_subaccount: IDL.Opt(IDL.Vec(IDL.Nat8)),
+        from: Account,
+        memo: IDL.Opt(IDL.Vec(IDL.Nat8)),
+        created_at_time: IDL.Opt(IDL.Nat64),
+        amount: IDL.Nat
+    });
+    const TransferFromError = IDL.Variant({
+        GenericError: IDL.Record({
+            message: IDL.Text,
+            error_code: IDL.Nat
+        }),
+        TemporarilyUnavailable: IDL.Null,
+        InsufficientAllowance: IDL.Record({ allowance: IDL.Nat }),
+        BadBurn: IDL.Record({ min_burn_amount: IDL.Nat }),
+        Duplicate: IDL.Record({ duplicate_of: IDL.Nat }),
+        BadFee: IDL.Record({ expected_fee: IDL.Nat }),
+        CreatedInFuture: IDL.Record({ ledger_time: IDL.Nat64 }),
+        TooOld: IDL.Null,
+        InsufficientFunds: IDL.Record({ balance: IDL.Nat })
+    });
+    const TransferFromResult = IDL.Variant({
+        Ok: IDL.Nat,
+        Err: TransferFromError
+    });
+    return IDL.Service({
+        icrc1_supported_standards: IDL.Func(
+            [],
+            [IDL.Vec(SupportedStandard)],
+            ['query']
+        ),
+        icrc2_allowance: IDL.Func(
+            [AllowanceArgs],
+            [AllowanceResult],
+            ['query']
+        ),
+        icrc2_approve: IDL.Func([ApproveArgs], [ApproveResult], []),
+        icrc2_transfer_from: IDL.Func(
+            [TransferFromArgs],
+            [TransferFromResult],
+            []
+        )
+    });
+};
+export const init: init = () => {
+    return [];
+};
diff --git a/canisters/icrc_3/ICRC-3.did b/canisters/icrc_3/ICRC-3.did
new file mode 100644
index 0000000000..196d515337
--- /dev/null
+++ b/canisters/icrc_3/ICRC-3.did
@@ -0,0 +1,59 @@
+// Taken from: https://github.com/dfinity/ICRC-1/blob/effeeaa89d8dd75ce3b2215b9c36eed98dafb7a8/standards/ICRC-3/ICRC-3.did
+
+type Value = variant {
+    Blob : blob;
+    Text : text;
+    Nat : nat;
+    Int : int;
+    Array : vec Value;
+    Map : vec record { text; Value };
+};
+
+type GetArchivesArgs = record {
+    // The last archive seen by the client.
+    // The Ledger will return archives coming
+    // after this one if set, otherwise it
+    // will return the first archives.
+    from : opt principal;
+};
+
+type GetArchivesResult = vec record {
+    // The id of the archive
+    canister_id : principal;
+
+    // The first block in the archive
+    start : nat;
+
+    // The last block in the archive
+    end : nat;
+};
+
+type GetBlocksArgs = vec record { start : nat; length : nat };
+
+type GetBlocksResult = record {
+    // Total number of blocks in the
+    // block log
+    log_length : nat;
+
+    blocks : vec record { id : nat; block: Value };
+
+    archived_blocks : vec record {
+        args : GetBlocksArgs;
+        callback : func (GetBlocksArgs) -> (GetBlocksResult) query;
+    };
+};
+
+type DataCertificate = record {
+  // See https://internetcomputer.org/docs/current/references/ic-interface-spec#certification
+  certificate : blob;
+
+  // CBOR encoded hash_tree
+  hash_tree : blob;
+};
+
+service : {
+  icrc3_get_archives : (GetArchivesArgs) -> (GetArchivesResult) query;
+  icrc3_get_tip_certificate : () -> (opt DataCertificate) query;
+  icrc3_get_blocks : (GetBlocksArgs) -> (GetBlocksResult) query;
+  icrc3_supported_block_types : () -> (vec record { block_type : text; url : text }) query;
+};
diff --git a/canisters/icrc_3/LICENSE b/canisters/icrc_3/LICENSE
new file mode 100644
index 0000000000..d645695673
--- /dev/null
+++ b/canisters/icrc_3/LICENSE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/canisters/icrc_3/index.ts b/canisters/icrc_3/index.ts
new file mode 100644
index 0000000000..3e718500b9
--- /dev/null
+++ b/canisters/icrc_3/index.ts
@@ -0,0 +1,155 @@
+import { ActorMethod } from '@dfinity/agent';
+import { IDL } from '@dfinity/candid';
+import { Principal } from '@dfinity/principal';
+export interface DataCertificate {
+    certificate: Uint8Array | number[];
+    hash_tree: Uint8Array | number[];
+}
+export interface GetArchivesArgs {
+    from: [] | [Principal];
+}
+export type GetArchivesResult = Array<{
+    end: bigint;
+    canister_id: Principal;
+    start: bigint;
+}>;
+export type GetBlocksArgs = Array<{ start: bigint; length: bigint }>;
+export interface GetBlocksResult {
+    log_length: bigint;
+    blocks: Array<{ id: bigint; block: Value }>;
+    archived_blocks: Array<{
+        args: GetBlocksArgs;
+        callback: [Principal, string];
+    }>;
+}
+export type Value =
+    | { Int: bigint }
+    | { Map: Array<[string, Value]> }
+    | { Nat: bigint }
+    | { Blob: Uint8Array | number[] }
+    | { Text: string }
+    | { Array: Array<Value> };
+export interface _SERVICE {
+    icrc3_get_archives: ActorMethod<[GetArchivesArgs], GetArchivesResult>;
+    icrc3_get_blocks: ActorMethod<[GetBlocksArgs], GetBlocksResult>;
+    icrc3_get_tip_certificate: ActorMethod<[], [] | [DataCertificate]>;
+    icrc3_supported_block_types: ActorMethod<
+        [],
+        Array<{ url: string; block_type: string }>
+    >;
+}
+export type idlFactory = IDL.InterfaceFactory;
+export type init = (args: { IDL: typeof IDL }) => IDL.Type[];
+export const GetBlocksResult = IDL.Rec();
+export const Value = IDL.Rec();
+export const GetArchivesArgs = IDL.Record({ from: IDL.Opt(IDL.Principal) });
+export const GetArchivesResult = IDL.Vec(
+    IDL.Record({
+        end: IDL.Nat,
+        canister_id: IDL.Principal,
+        start: IDL.Nat
+    })
+);
+export const GetBlocksArgs = IDL.Vec(
+    IDL.Record({ start: IDL.Nat, length: IDL.Nat })
+);
+Value.fill(
+    IDL.Variant({
+        Int: IDL.Int,
+        Map: IDL.Vec(IDL.Tuple(IDL.Text, Value)),
+        Nat: IDL.Nat,
+        Blob: IDL.Vec(IDL.Nat8),
+        Text: IDL.Text,
+        Array: IDL.Vec(Value)
+    })
+);
+GetBlocksResult.fill(
+    IDL.Record({
+        log_length: IDL.Nat,
+        blocks: IDL.Vec(IDL.Record({ id: IDL.Nat, block: Value })),
+        archived_blocks: IDL.Vec(
+            IDL.Record({
+                args: GetBlocksArgs,
+                callback: IDL.Func(
+                    [GetBlocksArgs],
+                    [GetBlocksResult],
+                    ['query']
+                )
+            })
+        )
+    })
+);
+export const DataCertificate = IDL.Record({
+    certificate: IDL.Vec(IDL.Nat8),
+    hash_tree: IDL.Vec(IDL.Nat8)
+});
+export const idlFactory: idlFactory = ({ IDL }) => {
+    const GetBlocksResult = IDL.Rec();
+    const Value = IDL.Rec();
+    const GetArchivesArgs = IDL.Record({ from: IDL.Opt(IDL.Principal) });
+    const GetArchivesResult = IDL.Vec(
+        IDL.Record({
+            end: IDL.Nat,
+            canister_id: IDL.Principal,
+            start: IDL.Nat
+        })
+    );
+    const GetBlocksArgs = IDL.Vec(
+        IDL.Record({ start: IDL.Nat, length: IDL.Nat })
+    );
+    Value.fill(
+        IDL.Variant({
+            Int: IDL.Int,
+            Map: IDL.Vec(IDL.Tuple(IDL.Text, Value)),
+            Nat: IDL.Nat,
+            Blob: IDL.Vec(IDL.Nat8),
+            Text: IDL.Text,
+            Array: IDL.Vec(Value)
+        })
+    );
+    GetBlocksResult.fill(
+        IDL.Record({
+            log_length: IDL.Nat,
+            blocks: IDL.Vec(IDL.Record({ id: IDL.Nat, block: Value })),
+            archived_blocks: IDL.Vec(
+                IDL.Record({
+                    args: GetBlocksArgs,
+                    callback: IDL.Func(
+                        [GetBlocksArgs],
+                        [GetBlocksResult],
+                        ['query']
+                    )
+                })
+            )
+        })
+    );
+    const DataCertificate = IDL.Record({
+        certificate: IDL.Vec(IDL.Nat8),
+        hash_tree: IDL.Vec(IDL.Nat8)
+    });
+    return IDL.Service({
+        icrc3_get_archives: IDL.Func(
+            [GetArchivesArgs],
+            [GetArchivesResult],
+            ['query']
+        ),
+        icrc3_get_blocks: IDL.Func(
+            [GetBlocksArgs],
+            [GetBlocksResult],
+            ['query']
+        ),
+        icrc3_get_tip_certificate: IDL.Func(
+            [],
+            [IDL.Opt(DataCertificate)],
+            ['query']
+        ),
+        icrc3_supported_block_types: IDL.Func(
+            [],
+            [IDL.Vec(IDL.Record({ url: IDL.Text, block_type: IDL.Text }))],
+            ['query']
+        )
+    });
+};
+export const init: init = () => {
+    return [];
+};
diff --git a/canisters/icrc_37/ICRC-37.did b/canisters/icrc_37/ICRC-37.did
new file mode 100644
index 0000000000..7ab067602c
--- /dev/null
+++ b/canisters/icrc_37/ICRC-37.did
@@ -0,0 +1,152 @@
+// Taken from: https://github.com/dfinity/ICRC/blob/946bd6518acb2aafd1828b93dfde9e47657fd758/ICRCs/ICRC-37/ICRC-37.did
+
+type Subaccount = blob;
+
+type Account = record { owner : principal; subaccount : opt Subaccount };
+
+type ApprovalInfo = record {
+    spender : Account;             // Approval is given to an ICRC Account
+    from_subaccount : opt blob;    // The subaccount the token can be transferred out from with the approval
+    expires_at : opt nat64;
+    memo : opt blob;
+    created_at_time : nat64; 
+};
+
+type ApproveTokenArg = record {
+    token_id : nat;
+    approval_info : ApprovalInfo;
+};
+
+type ApproveTokenResult = variant {
+    Ok : nat; // Transaction index for successful approval
+    Err : ApproveTokenError;
+};
+
+type ApproveTokenError = variant {
+    InvalidSpender;
+    Unauthorized;
+    NonExistingTokenId;
+    TooOld;
+    CreatedInFuture : record { ledger_time: nat64 };
+    GenericError : record { error_code : nat; message : text };
+    GenericBatchError : record { error_code : nat; message : text };
+};
+
+type ApproveCollectionArg = record {
+    approval_info : ApprovalInfo;
+};
+
+type ApproveCollectionResult = variant {
+    Ok : nat; // Transaction index for successful approval
+    Err : ApproveCollectionError;
+};
+
+type ApproveCollectionError = variant {
+    InvalidSpender;
+    TooOld;
+    CreatedInFuture : record { ledger_time: nat64 };
+    GenericError : record { error_code : nat; message : text };
+    GenericBatchError : record { error_code : nat; message : text };
+};
+
+type RevokeTokenApprovalArg = record {
+    spender : opt Account;      // null revokes matching approvals for all spenders
+    from_subaccount : opt blob; // null refers to the default subaccount
+    token_id : nat;
+    memo : opt blob;
+    created_at_time : opt nat64;
+};
+
+type RevokeTokenApprovalResponse = variant {
+    Ok : nat; // Transaction index for successful approval revocation
+    Err : RevokeTokenApprovalError;
+};
+
+type RevokeTokenApprovalError = variant {
+    ApprovalDoesNotExist;
+    Unauthorized;
+    NonExistingTokenId;
+    TooOld;
+    CreatedInFuture : record { ledger_time: nat64 };
+    GenericError : record { error_code : nat; message : text };
+    GenericBatchError : record { error_code : nat; message : text };
+};
+
+type RevokeCollectionApprovalArg = record {
+    spender : opt Account;      // null revokes approvals for all spenders that match the remaining parameters
+    from_subaccount : opt blob; // null refers to the default subaccount
+    memo : opt blob;
+    created_at_time : opt nat64;
+};
+
+type RevokeCollectionApprovalResult = variant {
+    Ok : nat; // Transaction index for successful approval revocation
+    Err : RevokeCollectionApprovalError;
+};
+
+type RevokeCollectionApprovalError = variant {
+    ApprovalDoesNotExist;
+    TooOld;
+    CreatedInFuture : record { ledger_time: nat64 };
+    GenericError : record { error_code : nat; message : text };
+    GenericBatchError : record { error_code : nat; message : text };
+};
+
+type IsApprovedArg = record {
+    spender : Account;
+    from_subaccount : opt blob;
+    token_id : nat;
+};
+
+type TokenApproval = record {
+    token_id : nat;
+    approval_info : ApprovalInfo;
+};
+
+type CollectionApproval = ApprovalInfo;
+
+type TransferFromArg = record {
+    spender_subaccount: opt blob; // The subaccount of the caller (used to identify the spender)
+    from : Account;
+    to : Account;
+    token_id : nat;
+    memo : opt blob;
+    created_at_time : opt nat64;
+};
+
+type TransferFromResult = variant {
+    Ok : nat; // Transaction index for successful transfer
+    Err : TransferFromError;
+};
+
+type TransferFromError = variant {
+    InvalidRecipient;
+    Unauthorized;
+    NonExistingTokenId;
+    TooOld;
+    CreatedInFuture : record { ledger_time: nat64 };
+    Duplicate : record { duplicate_of : nat };
+    GenericError : record { error_code : nat; message : text };
+    GenericBatchError : record { error_code : nat; message : text };
+};
+
+service : {
+  icrc37_max_approvals_per_token_or_collection : () -> (opt nat) query;
+  icrc37_max_revoke_approvals : () -> (opt nat) query;
+  icrc37_approve_tokens : (vec ApproveTokenArg)
+      -> (vec opt ApproveTokenResult);
+  icrc37_approve_collection : (vec ApproveCollectionArg)
+      -> (vec opt ApproveCollectionError);
+  icrc37_revoke_token_approvals: (vec RevokeTokenApprovalArg)
+      -> (vec opt RevokeTokenApprovalResponse);
+  icrc37_revoke_collection_approvals: (vec RevokeCollectionApprovalArg)
+      -> (vec opt RevokeCollectionApprovalResult);
+  icrc37_is_approved : (vec IsApprovedArg)
+      -> (vec bool) query;
+  icrc37_get_token_approvals : (token_id : nat, prev : opt TokenApproval, take : opt nat)
+      -> (vec TokenApproval) query;
+  icrc37_get_collection_approvals : (owner : Account, prev : opt CollectionApproval, take : opt nat)
+      -> (vec CollectionApproval) query;
+  icrc37_transfer_from : (vec TransferFromArg)
+      -> (vec opt TransferFromResult);
+}
diff --git a/canisters/icrc_37/LICENSE b/canisters/icrc_37/LICENSE
new file mode 100644
index 0000000000..d645695673
--- /dev/null
+++ b/canisters/icrc_37/LICENSE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/canisters/icrc_37/index.ts b/canisters/icrc_37/index.ts
new file mode 100644
index 0000000000..43f52ab952
--- /dev/null
+++ b/canisters/icrc_37/index.ts
@@ -0,0 +1,465 @@
+import { ActorMethod } from '@dfinity/agent';
+import { IDL } from '@dfinity/candid';
+import { Principal } from '@dfinity/principal';
+export interface Account {
+    owner: Principal;
+    subaccount: [] | [Subaccount];
+}
+export interface ApprovalInfo {
+    memo: [] | [Uint8Array | number[]];
+    from_subaccount: [] | [Uint8Array | number[]];
+    created_at_time: bigint;
+    expires_at: [] | [bigint];
+    spender: Account;
+}
+export interface ApproveCollectionArg {
+    approval_info: ApprovalInfo;
+}
+export type ApproveCollectionError =
+    | {
+          GenericError: { message: string; error_code: bigint };
+      }
+    | { InvalidSpender: null }
+    | { CreatedInFuture: { ledger_time: bigint } }
+    | { GenericBatchError: { message: string; error_code: bigint } }
+    | { TooOld: null };
+export type ApproveCollectionResult =
+    | { Ok: bigint }
+    | { Err: ApproveCollectionError };
+export interface ApproveTokenArg {
+    token_id: bigint;
+    approval_info: ApprovalInfo;
+}
+export type ApproveTokenError =
+    | {
+          GenericError: { message: string; error_code: bigint };
+      }
+    | { InvalidSpender: null }
+    | { NonExistingTokenId: null }
+    | { Unauthorized: null }
+    | { CreatedInFuture: { ledger_time: bigint } }
+    | { GenericBatchError: { message: string; error_code: bigint } }
+    | { TooOld: null };
+export type ApproveTokenResult = { Ok: bigint } | { Err: ApproveTokenError };
+export type CollectionApproval = ApprovalInfo;
+export interface IsApprovedArg {
+    token_id: bigint;
+    from_subaccount: [] | [Uint8Array | number[]];
+    spender: Account;
+}
+export interface RevokeCollectionApprovalArg {
+    memo: [] | [Uint8Array | number[]];
+    from_subaccount: [] | [Uint8Array | number[]];
+    created_at_time: [] | [bigint];
+    spender: [] | [Account];
+}
+export type RevokeCollectionApprovalError =
+    | {
+          GenericError: { message: string; error_code: bigint };
+      }
+    | { CreatedInFuture: { ledger_time: bigint } }
+    | { ApprovalDoesNotExist: null }
+    | { GenericBatchError: { message: string; error_code: bigint } }
+    | { TooOld: null };
+export type RevokeCollectionApprovalResult =
+    | { Ok: bigint }
+    | { Err: RevokeCollectionApprovalError };
+export interface RevokeTokenApprovalArg {
+    token_id: bigint;
+    memo: [] | [Uint8Array | number[]];
+    from_subaccount: [] | [Uint8Array | number[]];
+    created_at_time: [] | [bigint];
+    spender: [] | [Account];
+}
+export type RevokeTokenApprovalError =
+    | {
+          GenericError: { message: string; error_code: bigint };
+      }
+    | { NonExistingTokenId: null }
+    | { Unauthorized: null }
+    | { CreatedInFuture: { ledger_time: bigint } }
+    | { ApprovalDoesNotExist: null }
+    | { GenericBatchError: { message: string; error_code: bigint } }
+    | { TooOld: null };
+export type RevokeTokenApprovalResponse =
+    | { Ok: bigint }
+    | { Err: RevokeTokenApprovalError };
+export type Subaccount = Uint8Array | number[];
+export interface TokenApproval {
+    token_id: bigint;
+    approval_info: ApprovalInfo;
+}
+export interface TransferFromArg {
+    to: Account;
+    spender_subaccount: [] | [Uint8Array | number[]];
+    token_id: bigint;
+    from: Account;
+    memo: [] | [Uint8Array | number[]];
+    created_at_time: [] | [bigint];
+}
+export type TransferFromError =
+    | {
+          GenericError: { message: string; error_code: bigint };
+      }
+    | { Duplicate: { duplicate_of: bigint } }
+    | { NonExistingTokenId: null }
+    | { Unauthorized: null }
+    | { CreatedInFuture: { ledger_time: bigint } }
+    | { InvalidRecipient: null }
+    | { GenericBatchError: { message: string; error_code: bigint } }
+    | { TooOld: null };
+export type TransferFromResult = { Ok: bigint } | { Err: TransferFromError };
+export interface _SERVICE {
+    icrc37_approve_collection: ActorMethod<
+        [Array<ApproveCollectionArg>],
+        Array<[] | [ApproveCollectionError]>
+    >;
+    icrc37_approve_tokens: ActorMethod<
+        [Array<ApproveTokenArg>],
+        Array<[] | [ApproveTokenResult]>
+    >;
+    icrc37_get_collection_approvals: ActorMethod<
+        [Account, [] | [CollectionApproval], [] | [bigint]],
+        Array<CollectionApproval>
+    >;
+    icrc37_get_token_approvals: ActorMethod<
+        [bigint, [] | [TokenApproval], [] | [bigint]],
+        Array<TokenApproval>
+    >;
+    icrc37_is_approved: ActorMethod<[Array<IsApprovedArg>], Array<boolean>>;
+    icrc37_max_approvals_per_token_or_collection: ActorMethod<
+        [],
+        [] | [bigint]
+    >;
+    icrc37_max_revoke_approvals: ActorMethod<[], [] | [bigint]>;
+    icrc37_revoke_collection_approvals: ActorMethod<
+        [Array<RevokeCollectionApprovalArg>],
+        Array<[] | [RevokeCollectionApprovalResult]>
+    >;
+    icrc37_revoke_token_approvals: ActorMethod<
+        [Array<RevokeTokenApprovalArg>],
+        Array<[] | [RevokeTokenApprovalResponse]>
+    >;
+    icrc37_transfer_from: ActorMethod<
+        [Array<TransferFromArg>],
+        Array<[] | [TransferFromResult]>
+    >;
+}
+export type idlFactory = IDL.InterfaceFactory;
+export type init = (args: { IDL: typeof IDL }) => IDL.Type[];
+export const Subaccount = IDL.Vec(IDL.Nat8);
+export const Account = IDL.Record({
+    owner: IDL.Principal,
+    subaccount: IDL.Opt(Subaccount)
+});
+export const ApprovalInfo = IDL.Record({
+    memo: IDL.Opt(IDL.Vec(IDL.Nat8)),
+    from_subaccount: IDL.Opt(IDL.Vec(IDL.Nat8)),
+    created_at_time: IDL.Nat64,
+    expires_at: IDL.Opt(IDL.Nat64),
+    spender: Account
+});
+export const ApproveCollectionArg = IDL.Record({
+    approval_info: ApprovalInfo
+});
+export const ApproveCollectionError = IDL.Variant({
+    GenericError: IDL.Record({ message: IDL.Text, error_code: IDL.Nat }),
+    InvalidSpender: IDL.Null,
+    CreatedInFuture: IDL.Record({ ledger_time: IDL.Nat64 }),
+    GenericBatchError: IDL.Record({
+        message: IDL.Text,
+        error_code: IDL.Nat
+    }),
+    TooOld: IDL.Null
+});
+export const ApproveTokenArg = IDL.Record({
+    token_id: IDL.Nat,
+    approval_info: ApprovalInfo
+});
+export const ApproveTokenError = IDL.Variant({
+    GenericError: IDL.Record({ message: IDL.Text, error_code: IDL.Nat }),
+    InvalidSpender: IDL.Null,
+    NonExistingTokenId: IDL.Null,
+    Unauthorized: IDL.Null,
+    CreatedInFuture: IDL.Record({ ledger_time: IDL.Nat64 }),
+    GenericBatchError: IDL.Record({
+        message: IDL.Text,
+        error_code: IDL.Nat
+    }),
+    TooOld: IDL.Null
+});
+export const ApproveTokenResult = IDL.Variant({
+    Ok: IDL.Nat,
+    Err: ApproveTokenError
+});
+export const CollectionApproval = ApprovalInfo;
+export const TokenApproval = IDL.Record({
+    token_id: IDL.Nat,
+    approval_info: ApprovalInfo
+});
+export const IsApprovedArg = IDL.Record({
+    token_id: IDL.Nat,
+    from_subaccount: IDL.Opt(IDL.Vec(IDL.Nat8)),
+    spender: Account
+});
+export const RevokeCollectionApprovalArg = IDL.Record({
+    memo: IDL.Opt(IDL.Vec(IDL.Nat8)),
+    from_subaccount: IDL.Opt(IDL.Vec(IDL.Nat8)),
+    created_at_time: IDL.Opt(IDL.Nat64),
+    spender: IDL.Opt(Account)
+});
+export const RevokeCollectionApprovalError = IDL.Variant({
+    GenericError: IDL.Record({ message: IDL.Text, error_code: IDL.Nat }),
+    CreatedInFuture: IDL.Record({ ledger_time: IDL.Nat64 }),
+    ApprovalDoesNotExist: IDL.Null,
+    GenericBatchError: IDL.Record({
+        message: IDL.Text,
+        error_code: IDL.Nat
+    }),
+    TooOld: IDL.Null
+});
+export const RevokeCollectionApprovalResult = IDL.Variant({
+    Ok: IDL.Nat,
+    Err: RevokeCollectionApprovalError
+});
+export const RevokeTokenApprovalArg = IDL.Record({
+    token_id: IDL.Nat,
+    memo: IDL.Opt(IDL.Vec(IDL.Nat8)),
+    from_subaccount: IDL.Opt(IDL.Vec(IDL.Nat8)),
+    created_at_time: IDL.Opt(IDL.Nat64),
+    spender: IDL.Opt(Account)
+});
+export const RevokeTokenApprovalError = IDL.Variant({
+    GenericError: IDL.Record({ message: IDL.Text, error_code: IDL.Nat }),
+    NonExistingTokenId: IDL.Null,
+    Unauthorized: IDL.Null,
+    CreatedInFuture: IDL.Record({ ledger_time: IDL.Nat64 }),
+    ApprovalDoesNotExist: IDL.Null,
+    GenericBatchError: IDL.Record({
+        message: IDL.Text,
+        error_code: IDL.Nat
+    }),
+    TooOld: IDL.Null
+});
+export const RevokeTokenApprovalResponse = IDL.Variant({
+    Ok: IDL.Nat,
+    Err: RevokeTokenApprovalError
+});
+export const TransferFromArg = IDL.Record({
+    to: Account,
+    spender_subaccount: IDL.Opt(IDL.Vec(IDL.Nat8)),
+    token_id: IDL.Nat,
+    from: Account,
+    memo: IDL.Opt(IDL.Vec(IDL.Nat8)),
+    created_at_time: IDL.Opt(IDL.Nat64)
+});
+export const TransferFromError = IDL.Variant({
+    GenericError: IDL.Record({ message: IDL.Text, error_code: IDL.Nat }),
+    Duplicate: IDL.Record({ duplicate_of: IDL.Nat }),
+    NonExistingTokenId: IDL.Null,
+    Unauthorized: IDL.Null,
+    CreatedInFuture: IDL.Record({ ledger_time: IDL.Nat64 }),
+    InvalidRecipient: IDL.Null,
+    GenericBatchError: IDL.Record({
+        message: IDL.Text,
+        error_code: IDL.Nat
+    }),
+    TooOld: IDL.Null
+});
+export const TransferFromResult = IDL.Variant({
+    Ok: IDL.Nat,
+    Err: TransferFromError
+});
+export const idlFactory: idlFactory = ({ IDL }) => {
+    const Subaccount = IDL.Vec(IDL.Nat8);
+    const Account = IDL.Record({
+        owner: IDL.Principal,
+        subaccount: IDL.Opt(Subaccount)
+    });
+    const ApprovalInfo = IDL.Record({
+        memo: IDL.Opt(IDL.Vec(IDL.Nat8)),
+        from_subaccount: IDL.Opt(IDL.Vec(IDL.Nat8)),
+        created_at_time: IDL.Nat64,
+        expires_at: IDL.Opt(IDL.Nat64),
+        spender: Account
+    });
+    const ApproveCollectionArg = IDL.Record({ approval_info: ApprovalInfo });
+    const ApproveCollectionError = IDL.Variant({
+        GenericError: IDL.Record({
+            message: IDL.Text,
+            error_code: IDL.Nat
+        }),
+        InvalidSpender: IDL.Null,
+        CreatedInFuture: IDL.Record({ ledger_time: IDL.Nat64 }),
+        GenericBatchError: IDL.Record({
+            message: IDL.Text,
+            error_code: IDL.Nat
+        }),
+        TooOld: IDL.Null
+    });
+    const ApproveTokenArg = IDL.Record({
+        token_id: IDL.Nat,
+        approval_info: ApprovalInfo
+    });
+    const ApproveTokenError = IDL.Variant({
+        GenericError: IDL.Record({
+            message: IDL.Text,
+            error_code: IDL.Nat
+        }),
+        InvalidSpender: IDL.Null,
+        NonExistingTokenId: IDL.Null,
+        Unauthorized: IDL.Null,
+        CreatedInFuture: IDL.Record({ ledger_time: IDL.Nat64 }),
+        GenericBatchError: IDL.Record({
+            message: IDL.Text,
+            error_code: IDL.Nat
+        }),
+        TooOld: IDL.Null
+    });
+    const ApproveTokenResult = IDL.Variant({
+        Ok: IDL.Nat,
+        Err: ApproveTokenError
+    });
+    const CollectionApproval = ApprovalInfo;
+    const TokenApproval = IDL.Record({
+        token_id: IDL.Nat,
+        approval_info: ApprovalInfo
+    });
+    const IsApprovedArg = IDL.Record({
+        token_id: IDL.Nat,
+        from_subaccount: IDL.Opt(IDL.Vec(IDL.Nat8)),
+        spender: Account
+    });
+    const RevokeCollectionApprovalArg = IDL.Record({
+        memo: IDL.Opt(IDL.Vec(IDL.Nat8)),
+        from_subaccount: IDL.Opt(IDL.Vec(IDL.Nat8)),
+        created_at_time: IDL.Opt(IDL.Nat64),
+        spender: IDL.Opt(Account)
+    });
+    const RevokeCollectionApprovalError = IDL.Variant({
+        GenericError: IDL.Record({
+            message: IDL.Text,
+            error_code: IDL.Nat
+        }),
+        CreatedInFuture: IDL.Record({ ledger_time: IDL.Nat64 }),
+        ApprovalDoesNotExist: IDL.Null,
+        GenericBatchError: IDL.Record({
+            message: IDL.Text,
+            error_code: IDL.Nat
+        }),
+        TooOld: IDL.Null
+    });
+    const RevokeCollectionApprovalResult = IDL.Variant({
+        Ok: IDL.Nat,
+        Err: RevokeCollectionApprovalError
+    });
+    const RevokeTokenApprovalArg = IDL.Record({
+        token_id: IDL.Nat,
+        memo: IDL.Opt(IDL.Vec(IDL.Nat8)),
+        from_subaccount: IDL.Opt(IDL.Vec(IDL.Nat8)),
+        created_at_time: IDL.Opt(IDL.Nat64),
+        spender: IDL.Opt(Account)
+    });
+    const RevokeTokenApprovalError = IDL.Variant({
+        GenericError: IDL.Record({
+            message: IDL.Text,
+            error_code: IDL.Nat
+        }),
+        NonExistingTokenId: IDL.Null,
+        Unauthorized: IDL.Null,
+        CreatedInFuture: IDL.Record({ ledger_time: IDL.Nat64 }),
+        ApprovalDoesNotExist: IDL.Null,
+        GenericBatchError: IDL.Record({
+            message: IDL.Text,
+            error_code: IDL.Nat
+        }),
+        TooOld: IDL.Null
+    });
+    const RevokeTokenApprovalResponse = IDL.Variant({
+        Ok: IDL.Nat,
+        Err: RevokeTokenApprovalError
+    });
+    const TransferFromArg = IDL.Record({
+        to: Account,
+        spender_subaccount: IDL.Opt(IDL.Vec(IDL.Nat8)),
+        token_id: IDL.Nat,
+        from: Account,
+        memo: IDL.Opt(IDL.Vec(IDL.Nat8)),
+        created_at_time: IDL.Opt(IDL.Nat64)
+    });
+    const TransferFromError = IDL.Variant({
+        GenericError: IDL.Record({
+            message: IDL.Text,
+            error_code: IDL.Nat
+        }),
+        Duplicate: IDL.Record({ duplicate_of: IDL.Nat }),
+        NonExistingTokenId: IDL.Null,
+        Unauthorized: IDL.Null,
+        CreatedInFuture: IDL.Record({ ledger_time: IDL.Nat64 }),
+        InvalidRecipient: IDL.Null,
+        GenericBatchError: IDL.Record({
+            message: IDL.Text,
+            error_code: IDL.Nat
+        }),
+        TooOld: IDL.Null
+    });
+    const TransferFromResult = IDL.Variant({
+        Ok: IDL.Nat,
+        Err: TransferFromError
+    });
+    return IDL.Service({
+        icrc37_approve_collection: IDL.Func(
+            [IDL.Vec(ApproveCollectionArg)],
+            [IDL.Vec(IDL.Opt(ApproveCollectionError))],
+            []
+        ),
+        icrc37_approve_tokens: IDL.Func(
+            [IDL.Vec(ApproveTokenArg)],
+            [IDL.Vec(IDL.Opt(ApproveTokenResult))],
+            []
+        ),
+        icrc37_get_collection_approvals: IDL.Func(
+            [Account, IDL.Opt(CollectionApproval), IDL.Opt(IDL.Nat)],
+            [IDL.Vec(CollectionApproval)],
+            ['query']
+        ),
+        icrc37_get_token_approvals: IDL.Func(
+            [IDL.Nat, IDL.Opt(TokenApproval), IDL.Opt(IDL.Nat)],
+            [IDL.Vec(TokenApproval)],
+            ['query']
+        ),
+        icrc37_is_approved: IDL.Func(
+            [IDL.Vec(IsApprovedArg)],
+            [IDL.Vec(IDL.Bool)],
+            ['query']
+        ),
+        icrc37_max_approvals_per_token_or_collection: IDL.Func(
+            [],
+            [IDL.Opt(IDL.Nat)],
+            ['query']
+        ),
+        icrc37_max_revoke_approvals: IDL.Func(
+            [],
+            [IDL.Opt(IDL.Nat)],
+            ['query']
+        ),
+        icrc37_revoke_collection_approvals: IDL.Func(
+            [IDL.Vec(RevokeCollectionApprovalArg)],
+            [IDL.Vec(IDL.Opt(RevokeCollectionApprovalResult))],
+            []
+        ),
+        icrc37_revoke_token_approvals: IDL.Func(
+            [IDL.Vec(RevokeTokenApprovalArg)],
+            [IDL.Vec(IDL.Opt(RevokeTokenApprovalResponse))],
+            []
+        ),
+        icrc37_transfer_from: IDL.Func(
+            [IDL.Vec(TransferFromArg)],
+            [IDL.Vec(IDL.Opt(TransferFromResult))],
+            []
+        )
+    });
+};
+export const init: init = () => {
+    return [];
+};
diff --git a/canisters/icrc_7/ICRC-7.did b/canisters/icrc_7/ICRC-7.did
new file mode 100644
index 0000000000..a095f4ca58
--- /dev/null
+++ b/canisters/icrc_7/ICRC-7.did
@@ -0,0 +1,67 @@
+// Taken from: https://github.com/dfinity/ICRC/blob/946bd6518acb2aafd1828b93dfde9e47657fd758/ICRCs/ICRC-7/ICRC-7.did
+
+type Subaccount = blob;
+
+type Account = record { owner : principal; subaccount : opt Subaccount };
+
+// Generic value in accordance with ICRC-3
+type Value = variant { 
+    Blob : blob; 
+    Text : text; 
+    Nat : nat;
+    Int : int;
+    Array : vec Value; 
+    Map : vec record { text; Value }; 
+};
+
+type TransferArg = record {
+    from_subaccount: opt blob; // The subaccount to transfer the token from
+    to : Account;
+    token_id : nat;
+    memo : opt blob;
+    created_at_time : opt nat64;
+};
+
+type TransferResult = variant {
+    Ok : nat; // Transaction index for successful transfer
+    Err : TransferError;
+};
+
+type TransferError = variant {
+    NonExistingTokenId;
+    InvalidRecipient;
+    Unauthorized;
+    TooOld;
+    CreatedInFuture : record { ledger_time: nat64 };
+    Duplicate : record { duplicate_of : nat };
+    GenericError : record { error_code : nat; message : text };
+    GenericBatchError : record { error_code : nat; message : text };
+};
+
+service : {
+  icrc7_collection_metadata : () -> (vec record { text; Value } ) query;
+  icrc7_symbol : () -> (text) query;
+  icrc7_name : () -> (text) query;
+  icrc7_description : () -> (opt text) query;
+  icrc7_logo : () -> (opt text) query;
+  icrc7_total_supply : () -> (nat) query;
+  icrc7_supply_cap : () -> (opt nat) query;
+  icrc7_max_query_batch_size : () -> (opt nat) query;
+  icrc7_max_update_batch_size : () -> (opt nat) query;
+  icrc7_default_take_value : () -> (opt nat) query;
+  icrc7_max_take_value : () -> (opt nat) query;
+  icrc7_max_memo_size : () -> (opt nat) query;
+  icrc7_atomic_batch_transfers : () -> (opt bool) query;
+  icrc7_tx_window : () -> (opt nat) query;
+  icrc7_permitted_drift : () -> (opt nat) query;
+  icrc7_token_metadata : (token_ids : vec nat)
+      -> (vec opt vec record { text; Value }) query;
+  icrc7_owner_of : (token_ids : vec nat)
+      -> (vec opt Account) query;
+  icrc7_balance_of : (vec Account) -> (vec nat) query;
+  icrc7_tokens : (prev : opt nat, take : opt nat)
+      -> (vec nat) query;
+  icrc7_tokens_of : (account : Account, prev : opt nat, take : opt nat)
+      -> (vec nat) query;
+  icrc7_transfer : (vec TransferArg) -> (vec opt TransferResult);
+}
diff --git a/canisters/icrc_7/LICENSE b/canisters/icrc_7/LICENSE
new file mode 100644
index 0000000000..d645695673
--- /dev/null
+++ b/canisters/icrc_7/LICENSE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/canisters/icrc_7/index.ts b/canisters/icrc_7/index.ts
new file mode 100644
index 0000000000..d74c046e39
--- /dev/null
+++ b/canisters/icrc_7/index.ts
@@ -0,0 +1,212 @@
+import { ActorMethod } from '@dfinity/agent';
+import { IDL } from '@dfinity/candid';
+import { Principal } from '@dfinity/principal';
+export interface Account {
+    owner: Principal;
+    subaccount: [] | [Subaccount];
+}
+export type Subaccount = Uint8Array | number[];
+export interface TransferArg {
+    to: Account;
+    token_id: bigint;
+    memo: [] | [Uint8Array | number[]];
+    from_subaccount: [] | [Uint8Array | number[]];
+    created_at_time: [] | [bigint];
+}
+export type TransferError =
+    | {
+          GenericError: { message: string; error_code: bigint };
+      }
+    | { Duplicate: { duplicate_of: bigint } }
+    | { NonExistingTokenId: null }
+    | { Unauthorized: null }
+    | { CreatedInFuture: { ledger_time: bigint } }
+    | { InvalidRecipient: null }
+    | { GenericBatchError: { message: string; error_code: bigint } }
+    | { TooOld: null };
+export type TransferResult = { Ok: bigint } | { Err: TransferError };
+export type Value =
+    | { Int: bigint }
+    | { Map: Array<[string, Value]> }
+    | { Nat: bigint }
+    | { Blob: Uint8Array | number[] }
+    | { Text: string }
+    | { Array: Array<Value> };
+export interface _SERVICE {
+    icrc7_atomic_batch_transfers: ActorMethod<[], [] | [boolean]>;
+    icrc7_balance_of: ActorMethod<[Array<Account>], Array<bigint>>;
+    icrc7_collection_metadata: ActorMethod<[], Array<[string, Value]>>;
+    icrc7_default_take_value: ActorMethod<[], [] | [bigint]>;
+    icrc7_description: ActorMethod<[], [] | [string]>;
+    icrc7_logo: ActorMethod<[], [] | [string]>;
+    icrc7_max_memo_size: ActorMethod<[], [] | [bigint]>;
+    icrc7_max_query_batch_size: ActorMethod<[], [] | [bigint]>;
+    icrc7_max_take_value: ActorMethod<[], [] | [bigint]>;
+    icrc7_max_update_batch_size: ActorMethod<[], [] | [bigint]>;
+    icrc7_name: ActorMethod<[], string>;
+    icrc7_owner_of: ActorMethod<[Array<bigint>], Array<[] | [Account]>>;
+    icrc7_permitted_drift: ActorMethod<[], [] | [bigint]>;
+    icrc7_supply_cap: ActorMethod<[], [] | [bigint]>;
+    icrc7_symbol: ActorMethod<[], string>;
+    icrc7_token_metadata: ActorMethod<
+        [Array<bigint>],
+        Array<[] | [Array<[string, Value]>]>
+    >;
+    icrc7_tokens: ActorMethod<[[] | [bigint], [] | [bigint]], Array<bigint>>;
+    icrc7_tokens_of: ActorMethod<
+        [Account, [] | [bigint], [] | [bigint]],
+        Array<bigint>
+    >;
+    icrc7_total_supply: ActorMethod<[], bigint>;
+    icrc7_transfer: ActorMethod<
+        [Array<TransferArg>],
+        Array<[] | [TransferResult]>
+    >;
+    icrc7_tx_window: ActorMethod<[], [] | [bigint]>;
+}
+export type idlFactory = IDL.InterfaceFactory;
+export type init = (args: { IDL: typeof IDL }) => IDL.Type[];
+export const Value = IDL.Rec();
+export const Subaccount = IDL.Vec(IDL.Nat8);
+export const Account = IDL.Record({
+    owner: IDL.Principal,
+    subaccount: IDL.Opt(Subaccount)
+});
+Value.fill(
+    IDL.Variant({
+        Int: IDL.Int,
+        Map: IDL.Vec(IDL.Tuple(IDL.Text, Value)),
+        Nat: IDL.Nat,
+        Blob: IDL.Vec(IDL.Nat8),
+        Text: IDL.Text,
+        Array: IDL.Vec(Value)
+    })
+);
+export const TransferArg = IDL.Record({
+    to: Account,
+    token_id: IDL.Nat,
+    memo: IDL.Opt(IDL.Vec(IDL.Nat8)),
+    from_subaccount: IDL.Opt(IDL.Vec(IDL.Nat8)),
+    created_at_time: IDL.Opt(IDL.Nat64)
+});
+export const TransferError = IDL.Variant({
+    GenericError: IDL.Record({ message: IDL.Text, error_code: IDL.Nat }),
+    Duplicate: IDL.Record({ duplicate_of: IDL.Nat }),
+    NonExistingTokenId: IDL.Null,
+    Unauthorized: IDL.Null,
+    CreatedInFuture: IDL.Record({ ledger_time: IDL.Nat64 }),
+    InvalidRecipient: IDL.Null,
+    GenericBatchError: IDL.Record({
+        message: IDL.Text,
+        error_code: IDL.Nat
+    }),
+    TooOld: IDL.Null
+});
+export const TransferResult = IDL.Variant({
+    Ok: IDL.Nat,
+    Err: TransferError
+});
+export const idlFactory: idlFactory = ({ IDL }) => {
+    const Value = IDL.Rec();
+    const Subaccount = IDL.Vec(IDL.Nat8);
+    const Account = IDL.Record({
+        owner: IDL.Principal,
+        subaccount: IDL.Opt(Subaccount)
+    });
+    Value.fill(
+        IDL.Variant({
+            Int: IDL.Int,
+            Map: IDL.Vec(IDL.Tuple(IDL.Text, Value)),
+            Nat: IDL.Nat,
+            Blob: IDL.Vec(IDL.Nat8),
+            Text: IDL.Text,
+            Array: IDL.Vec(Value)
+        })
+    );
+    const TransferArg = IDL.Record({
+        to: Account,
+        token_id: IDL.Nat,
+        memo: IDL.Opt(IDL.Vec(IDL.Nat8)),
+        from_subaccount: IDL.Opt(IDL.Vec(IDL.Nat8)),
+        created_at_time: IDL.Opt(IDL.Nat64)
+    });
+    const TransferError = IDL.Variant({
+        GenericError: IDL.Record({
+            message: IDL.Text,
+            error_code: IDL.Nat
+        }),
+        Duplicate: IDL.Record({ duplicate_of: IDL.Nat }),
+        NonExistingTokenId: IDL.Null,
+        Unauthorized: IDL.Null,
+        CreatedInFuture: IDL.Record({ ledger_time: IDL.Nat64 }),
+        InvalidRecipient: IDL.Null,
+        GenericBatchError: IDL.Record({
+            message: IDL.Text,
+            error_code: IDL.Nat
+        }),
+        TooOld: IDL.Null
+    });
+    const TransferResult = IDL.Variant({ Ok: IDL.Nat, Err: TransferError });
+    return IDL.Service({
+        icrc7_atomic_batch_transfers: IDL.Func(
+            [],
+            [IDL.Opt(IDL.Bool)],
+            ['query']
+        ),
+        icrc7_balance_of: IDL.Func(
+            [IDL.Vec(Account)],
+            [IDL.Vec(IDL.Nat)],
+            ['query']
+        ),
+        icrc7_collection_metadata: IDL.Func(
+            [],
+            [IDL.Vec(IDL.Tuple(IDL.Text, Value))],
+            ['query']
+        ),
+        icrc7_default_take_value: IDL.Func([], [IDL.Opt(IDL.Nat)], ['query']),
+        icrc7_description: IDL.Func([], [IDL.Opt(IDL.Text)], ['query']),
+        icrc7_logo: IDL.Func([], [IDL.Opt(IDL.Text)], ['query']),
+        icrc7_max_memo_size: IDL.Func([], [IDL.Opt(IDL.Nat)], ['query']),
+        icrc7_max_query_batch_size: IDL.Func([], [IDL.Opt(IDL.Nat)], ['query']),
+        icrc7_max_take_value: IDL.Func([], [IDL.Opt(IDL.Nat)], ['query']),
+        icrc7_max_update_batch_size: IDL.Func(
+            [],
+            [IDL.Opt(IDL.Nat)],
+            ['query']
+        ),
+        icrc7_name: IDL.Func([], [IDL.Text], ['query']),
+        icrc7_owner_of: IDL.Func(
+            [IDL.Vec(IDL.Nat)],
+            [IDL.Vec(IDL.Opt(Account))],
+            ['query']
+        ),
+        icrc7_permitted_drift: IDL.Func([], [IDL.Opt(IDL.Nat)], ['query']),
+        icrc7_supply_cap: IDL.Func([], [IDL.Opt(IDL.Nat)], ['query']),
+        icrc7_symbol: IDL.Func([], [IDL.Text], ['query']),
+        icrc7_token_metadata: IDL.Func(
+            [IDL.Vec(IDL.Nat)],
+            [IDL.Vec(IDL.Opt(IDL.Vec(IDL.Tuple(IDL.Text, Value))))],
+            ['query']
+        ),
+        icrc7_tokens: IDL.Func(
+            [IDL.Opt(IDL.Nat), IDL.Opt(IDL.Nat)],
+            [IDL.Vec(IDL.Nat)],
+            ['query']
+        ),
+        icrc7_tokens_of: IDL.Func(
+            [Account, IDL.Opt(IDL.Nat), IDL.Opt(IDL.Nat)],
+            [IDL.Vec(IDL.Nat)],
+            ['query']
+        ),
+        icrc7_total_supply: IDL.Func([], [IDL.Nat], ['query']),
+        icrc7_transfer: IDL.Func(
+            [IDL.Vec(TransferArg)],
+            [IDL.Vec(IDL.Opt(TransferResult))],
+            []
+        ),
+        icrc7_tx_window: IDL.Func([], [IDL.Opt(IDL.Nat)], ['query'])
+    });
+};
+export const init: init = () => {
+    return [];
+};
diff --git a/canisters/ledger/index.ts b/canisters/ledger/index.ts
deleted file mode 100644
index daf4876a37..0000000000
--- a/canisters/ledger/index.ts
+++ /dev/null
@@ -1,470 +0,0 @@
-// Some JS docs licensed under:
-//
-// - https://github.com/dfinity/cdk-rs/blob/main/LICENSE
-// - https://github.com/dfinity/interface-spec/blob/master/LICENSE
-// - https://github.com/dfinity/portal/blob/master/LICENSE
-//
-// Some documentation changed from original work.
-
-import { IDL } from '@dfinity/candid';
-import { Principal } from '@dfinity/principal';
-
-import * as icrc from '../icrc';
-
-// Amount of tokens, measured in 10^-8 of a token.
-export const Tokens = IDL.Record({
-    e8s: IDL.Nat64
-});
-export type Tokens = {
-    e8s: bigint;
-};
-
-// Number of nanoseconds from the UNIX epoch in UTC timezone.
-export const TimeStamp = IDL.Record({
-    timestamp_nanos: IDL.Nat64
-});
-export type TimeStamp = {
-    timestamp_nanos: bigint;
-};
-
-// AccountIdentifier is a 32-byte array.
-// The first 4 bytes is big-endian encoding of a CRC32 checksum of the last 28 bytes.
-export const AccountIdentifier = IDL.Vec(IDL.Nat8);
-export type AccountIdentifier = Uint8Array;
-
-// Subaccount is an arbitrary 32-byte byte array.
-// Ledger uses subaccounts to compute the source address, which enables one
-// principal to control multiple ledger accounts.
-export const SubAccount = IDL.Vec(IDL.Nat8);
-export type SubAccount = Uint8Array;
-
-// Sequence number of a block produced by the ledger.
-export const BlockIndex = IDL.Nat64;
-export type BlockIndex = bigint;
-
-// An arbitrary number associated with a transaction.
-// The caller can set it in a `transfer` call as a correlation identifier.
-export const Memo = IDL.Nat64;
-export type Memo = bigint;
-
-// Arguments for the `transfer` call.
-export const TransferArgs = IDL.Record({
-    // Transaction memo.
-    // See comments for the `Memo` type.
-    memo: Memo,
-    // The amount that the caller wants to transfer to the destination address.
-    amount: Tokens,
-    // The amount that the caller pays for the transaction.
-    // Must be 10000 e8s.
-    fee: Tokens,
-    // The subaccount from which the caller wants to transfer funds.
-    // If null, the ledger uses the default (all zeros) subaccount to compute the source address.
-    // See comments for the `SubAccount` type.
-    from_subaccount: IDL.Opt(SubAccount),
-    // The destination account.
-    // If the transfer is successful, the balance of this address increases by `amount`.
-    to: AccountIdentifier,
-    // The point in time when the caller created this request.
-    // If null, the ledger uses current IC time as the timestamp.
-    created_at_time: IDL.Opt(TimeStamp)
-});
-export type TransferArgs = {
-    memo: Memo;
-    amount: Tokens;
-    fee: Tokens;
-    from_subaccount: [SubAccount] | [];
-    to: AccountIdentifier;
-    created_at_time: [TimeStamp] | [];
-};
-
-export const BadFee = IDL.Record({
-    expected_fee: Tokens
-});
-export type BadFee = {
-    expected_fee: Tokens;
-};
-
-export const InsufficientFunds = IDL.Record({
-    balance: Tokens
-});
-export type InsufficientFunds = {
-    balance: Tokens;
-};
-
-export const TxTooOld = IDL.Record({
-    allowed_window_nanos: IDL.Nat64
-});
-export type TxTooOld = {
-    allowed_window_nanos: bigint;
-};
-
-export const TxDuplicate = IDL.Record({
-    duplicate_of: BlockIndex
-});
-export type TxDuplicate = {
-    duplicate_of: BlockIndex;
-};
-
-export const TransferError = IDL.Variant({
-    // The fee that the caller specified in the transfer request was not the one that ledger expects.
-    // The caller can change the transfer fee to the `expected_fee` and retry the request.
-    BadFee: BadFee,
-    // The account specified by the caller doesn't have enough funds.
-    InsufficientFunds: InsufficientFunds,
-    // The request is too old.
-    // The ledger only accepts requests created within 24 hours window.
-    // This is a non-recoverable error.
-    TxTooOld: TxTooOld,
-    // The caller specified `created_at_time` that is too far in future.
-    // The caller can retry the request later.
-    TxCreatedInFuture: IDL.Null,
-    // The ledger has already executed the request.
-    // `duplicate_of` field is equal to the index of the block containing the original transaction.
-    TxDuplicate: TxDuplicate
-});
-export type TransferError =
-    | {
-          BadFee: BadFee;
-      }
-    | {
-          InsufficientFunds: InsufficientFunds;
-      }
-    | {
-          TxTooOld: TxTooOld;
-      }
-    | {
-          TxCreatedInFuture: null;
-      }
-    | {
-          TxDuplicate: TxDuplicate;
-      };
-
-export const TransferResult = IDL.Variant({
-    Ok: IDL.Nat64,
-    Err: TransferError
-});
-export type TransferResult =
-    | {
-          Ok: bigint;
-      }
-    | {
-          Err: TransferError;
-      };
-
-// Arguments for the `account_balance` call.
-export const AccountBalanceArgs = IDL.Record({
-    account: AccountIdentifier
-});
-export type AccountBalanceArgs = {
-    account: AccountIdentifier;
-};
-
-export const TransferFeeArg = IDL.Record({});
-export type TransferFeeArg = Record<string, never>;
-
-export const TransferFee = IDL.Record({
-    // The fee to pay to perform a transfer
-    transfer_fee: Tokens
-});
-export type TransferFee = {
-    transfer_fee: Tokens;
-};
-
-export const GetBlocksArgs = IDL.Record({
-    // The index of the first block to fetch.
-    start: BlockIndex,
-    // Max number of blocks to fetch.
-    length: IDL.Nat64
-});
-export type GetBlocksArgs = {
-    start: BlockIndex;
-    length: bigint;
-};
-
-export const Mint = IDL.Record({
-    to: AccountIdentifier,
-    amount: Tokens
-});
-export type Mint = {
-    to: AccountIdentifier;
-    amount: Tokens;
-};
-
-export const Burn = IDL.Record({
-    from: AccountIdentifier,
-    amount: Tokens
-});
-export type Burn = {
-    from: AccountIdentifier;
-    amount: Tokens;
-};
-
-export const Transfer = IDL.Record({
-    from: AccountIdentifier,
-    to: AccountIdentifier,
-    amount: Tokens,
-    fee: Tokens
-});
-export type Transfer = {
-    from: AccountIdentifier;
-    to: AccountIdentifier;
-    amount: Tokens;
-    fee: Tokens;
-};
-
-export const Operation = IDL.Variant({
-    Mint: Mint,
-    Burn: Burn,
-    Transfer: Transfer
-});
-export type Operation =
-    | {
-          Mint: Mint;
-      }
-    | {
-          Burn: Burn;
-      }
-    | {
-          Transfer: Transfer;
-      };
-
-export const Transaction = IDL.Record({
-    memo: Memo,
-    operation: IDL.Opt(Operation),
-    created_at_time: TimeStamp
-});
-export type Transaction = {
-    memo: Memo;
-    operation: Operation | null;
-    created_at_time: TimeStamp;
-};
-
-export const Block = IDL.Record({
-    parent_hash: IDL.Opt(IDL.Vec(IDL.Nat8)),
-    transaction: Transaction,
-    timestamp: TimeStamp
-});
-export type Block = {
-    parent_hash: Uint8Array | null;
-    transaction: Transaction;
-    timestamp: TimeStamp;
-};
-
-// A prefix of the block range specified in the [GetBlocksArgs] request.
-export const BlockRange = IDL.Record({
-    // A prefix of the requested block range.
-    // The index of the first block is equal to [GetBlocksArgs.from].
-    //
-    // Note that the number of blocks might be less than the requested
-    // [GetBlocksArgs.len] for various reasons, for example:
-    //
-    // 1. The query might have hit the replica with an outdated state
-    //    that doesn't have the full block range yet.
-    // 2. The requested range is too large to fit into a single reply.
-    //
-    // NOTE: the list of blocks can be empty if:
-    // 1. [GetBlocksArgs.len] was zero.
-    // 2. [GetBlocksArgs.from] was larger than the last block known to the canister.
-    blocks: IDL.Vec(Block)
-});
-export type BlockRange = {
-    blocks: Block[];
-};
-
-export const BadFirstBlockIndex = IDL.Record({
-    requested_index: BlockIndex,
-    first_valid_index: BlockIndex
-});
-export type BadFirstBlockIndex = {
-    requested_index: BlockIndex;
-    first_valid_index: BlockIndex;
-};
-
-export const Other = IDL.Record({
-    error_code: IDL.Nat64,
-    error_message: IDL.Text
-});
-export type Other = {
-    error_code: bigint;
-    error_message: string;
-};
-
-// An error indicating that the arguments passed to [QueryArchiveFn] were invalid.
-export const QueryArchiveError = IDL.Variant({
-    // [GetBlocksArgs.from] argument was smaller than the first block
-    // served by the canister that received the request.
-    BadFirstBlockIndex: BadFirstBlockIndex,
-    // Reserved for future use.
-    Other: Other
-});
-export type QueryArchiveError =
-    | {
-          BadFirstBlockIndex?: BadFirstBlockIndex;
-      }
-    | {
-          Other?: Other;
-      };
-
-export const QueryArchiveResult = IDL.Variant({
-    // Successfully fetched zero or more blocks.
-    Ok: BlockRange,
-    // The [GetBlocksArgs] request was invalid.
-    Err: QueryArchiveError
-});
-export type QueryArchiveResult =
-    | {
-          Ok: BlockRange;
-      }
-    | {
-          Err: QueryArchiveError;
-      };
-
-// A function that is used for fetching archived ledger blocks.
-export const QueryArchiveFn = IDL.Func(
-    [GetBlocksArgs],
-    [QueryArchiveResult],
-    ['query']
-);
-export type QueryArchiveFn = (
-    args: GetBlocksArgs
-) => Promise<QueryArchiveResult>;
-
-export const ArchivedBlock = IDL.Record({
-    // The index of the first archived block that can be fetched using the callback.
-    start: BlockIndex,
-    // The number of blocks that can be fetch using the callback.
-    length: IDL.Nat64,
-    // The function that should be called to fetch the archived blocks.
-    // The range of the blocks accessible using this function is given by [from]
-    // and [len] fields above.
-    callback: QueryArchiveFn
-});
-export type ArchivedBlock = {
-    start: BlockIndex;
-    length: bigint;
-    callback: QueryArchiveFn;
-};
-
-// The result of a "query_blocks" call.
-//
-// The structure of the result is somewhat complicated because the main ledger canister might
-// not have all the blocks that the caller requested: One or more "archive" canisters might
-// store some of the requested blocks.
-//
-// Note: as of Q4 2021 when this interface is authored, the IC doesn't support making nested
-// query calls within a query call.
-export const QueryBlocksResponse = IDL.Record({
-    // The total number of blocks in the chain.
-    // If the chain length is positive, the index of the last block is `chain_len - 1`.
-    chain_length: IDL.Nat64,
-    // System certificate for the hash of the latest block in the chain.
-    // Only present if `query_blocks` is called in a non-replicated query conIDL.Text.
-    certificate: IDL.Opt(IDL.Vec(IDL.Nat8)),
-    // List of blocks that were available in the ledger when it processed the call.
-    //
-    // The blocks form a contiguous range, with the first block having index
-    // [first_block_index] (see below), and the last block having index
-    // [first_block_index] + len(blocks) - 1.
-    //
-    // The block range can be an arbitrary sub-range of the originally requested range.
-    blocks: IDL.Vec(Block),
-    // The index of the first block in "blocks".
-    // If the blocks vector is empty, the exact value of this field is not specified.
-    first_block_index: BlockIndex,
-    // Encoding of instructions for fetching archived blocks whose indices fall into the
-    // requested range.
-    //
-    // For each entry `e` in [archived_blocks], `[e.from, e.from + len)` is a sub-range
-    // of the originally requested block range.
-    archived_blocks: IDL.Vec(ArchivedBlock)
-});
-export type QueryBlocksResponse = {
-    chain_length: bigint;
-    certificate: Uint8Array | null;
-    blocks: Block[];
-    first_block_index: BlockIndex;
-    archived_blocks: ArchivedBlock[];
-};
-
-export const Archive = IDL.Record({
-    canister_id: IDL.Principal
-});
-export type Archive = {
-    canister_id: Principal;
-};
-
-export const Archives = IDL.Record({
-    archives: IDL.Vec(Archive)
-});
-export type Archives = {
-    archives: Archive[];
-};
-
-export const SymbolResult = IDL.Record({
-    symbol: IDL.Text
-});
-export type SymbolResult = {
-    symbol: string;
-};
-
-export const NameResult = IDL.Record({
-    name: IDL.Text
-});
-export type NameResult = {
-    name: string;
-};
-
-export const DecimalsResult = IDL.Record({
-    decimals: IDL.Nat32
-});
-export type DecimalsResult = {
-    decimals: number;
-};
-
-export const Address = IDL.Text;
-export type Address = string;
-
-export const Ledger = IDL.Service({
-    // Transfers tokens from a subaccount of the caller to the destination address.
-    // The source address is computed from the principal of the caller and the specified subaccount.
-    // When successful, returns the index of the block containing the transaction.
-    transfer: IDL.Func([TransferArgs], [TransferResult]),
-    // Returns the amount of Tokens on the specified account.
-    account_balance: IDL.Func([AccountBalanceArgs], [Tokens], ['query']),
-    // Returns the current transfer_fee.
-    transfer_fee: IDL.Func([TransferFeeArg], [TransferFee], ['query']),
-    // Queries blocks in the specified range.
-    query_blocks: IDL.Func([GetBlocksArgs], [QueryBlocksResponse], ['query']),
-    // Returns token symbol.
-    symbol: IDL.Func([], [SymbolResult], ['query']),
-    // Returns token name.
-    name: IDL.Func([], [NameResult], ['query']),
-    // Returns token decimals.
-    decimals: IDL.Func([], [DecimalsResult], ['query']),
-    // Returns the existing archive canisters information.
-    archives: IDL.Func([], [Archives], ['query']),
-    icrc1_metadata: IDL.Func(
-        [],
-        [IDL.Vec(IDL.Tuple(IDL.Text, icrc.Value))],
-        ['query']
-    ),
-    icrc1_name: IDL.Func([], [IDL.Text], ['query']),
-    icrc1_symbol: IDL.Func([], [IDL.Text], ['query']),
-    icrc1_decimals: IDL.Func([], [IDL.Nat8], ['query']),
-    icrc1_fee: IDL.Func([], [IDL.Nat], ['query']),
-    icrc1_total_supply: IDL.Func([], [IDL.Nat], ['query']),
-    icrc1_minting_account: IDL.Func([], [IDL.Opt(icrc.Account)], ['query']),
-    icrc1_balance_of: IDL.Func([icrc.Account], [IDL.Nat], ['query']),
-    icrc1_transfer: IDL.Func([icrc.TransferArgs], [icrc.TransferResult]),
-    icrc1_supported_standards: IDL.Func(
-        [],
-        [IDL.Vec(icrc.SupportedStandard)],
-        ['query']
-    )
-});
-
-export {
-    binaryAddressFromAddress,
-    binaryAddressFromPrincipal,
-    hexAddressFromPrincipal
-} from './address';
diff --git a/tests/end_to_end/candid_rpc/class_syntax/icrc/canisters/proxy/index.ts b/tests/end_to_end/candid_rpc/class_syntax/icrc/canisters/proxy/index.ts
index a4276fe946..5cb74c2d07 100644
--- a/tests/end_to_end/candid_rpc/class_syntax/icrc/canisters/proxy/index.ts
+++ b/tests/end_to_end/candid_rpc/class_syntax/icrc/canisters/proxy/index.ts
@@ -1,17 +1,19 @@
 import { call, IDL, query, trap, update } from 'azle';
 import {
     Account,
+    TransferArgs,
+    TransferResult,
+    Value
+} from 'azle/canisters/icrc_1';
+import {
     AllowanceArgs,
     AllowanceResult,
     ApproveArgs,
     ApproveResult,
     SupportedStandard,
-    TransferArgs,
     TransferFromArgs,
-    TransferFromResult,
-    TransferResult,
-    Value
-} from 'azle/canisters/icrc';
+    TransferFromResult
+} from 'azle/canisters/icrc_2';
 
 export default class {
     @query([], IDL.Vec(IDL.Tuple(IDL.Text, Value)), { composite: true })
diff --git a/tests/end_to_end/candid_rpc/class_syntax/icrc/package-lock.json b/tests/end_to_end/candid_rpc/class_syntax/icrc/package-lock.json
index 4a3752d908..5c6e4aef81 100644
--- a/tests/end_to_end/candid_rpc/class_syntax/icrc/package-lock.json
+++ b/tests/end_to_end/candid_rpc/class_syntax/icrc/package-lock.json
@@ -17,6 +17,7 @@
             }
         },
         "../../functional_syntax/icrc": {
+            "name": "icrc_end_to_end_test_functional_syntax",
             "dev": true,
             "dependencies": {
                 "azle": "0.24.1"
diff --git a/tests/end_to_end/candid_rpc/class_syntax/ledger_canister/package-lock.json b/tests/end_to_end/candid_rpc/class_syntax/ledger_canister/package-lock.json
index f9e0bc2ead..0263cec7dc 100644
--- a/tests/end_to_end/candid_rpc/class_syntax/ledger_canister/package-lock.json
+++ b/tests/end_to_end/candid_rpc/class_syntax/ledger_canister/package-lock.json
@@ -17,6 +17,7 @@
             }
         },
         "../../functional_syntax/ledger_canister": {
+            "name": "ledger_canister_end_to_end_test_functional_syntax",
             "dev": true,
             "dependencies": {
                 "azle": "0.24.1"
diff --git a/tests/end_to_end/candid_rpc/class_syntax/ledger_canister/src/ledger_canister/index.ts b/tests/end_to_end/candid_rpc/class_syntax/ledger_canister/src/ledger_canister/index.ts
index d27a16bd9a..625f9c4d3a 100644
--- a/tests/end_to_end/candid_rpc/class_syntax/ledger_canister/src/ledger_canister/index.ts
+++ b/tests/end_to_end/candid_rpc/class_syntax/ledger_canister/src/ledger_canister/index.ts
@@ -1,7 +1,6 @@
 import { call, IDL, Principal, query, update } from 'azle';
 import {
     AccountBalanceArgs,
-    Address,
     Archives,
     binaryAddressFromAddress,
     DecimalsResult,
@@ -15,12 +14,15 @@ import {
     TransferFee,
     TransferFeeArg,
     TransferResult
-} from 'azle/canisters/ledger';
+} from 'azle/canisters/icp';
 
 export default class {
-    @update([Address, IDL.Nat64, IDL.Nat64, IDL.Opt(IDL.Nat64)], TransferResult)
+    @update(
+        [IDL.Text, IDL.Nat64, IDL.Nat64, IDL.Opt(IDL.Nat64)],
+        TransferResult
+    )
     async executeTransfer(
-        to: Address,
+        to: string,
         amount: bigint,
         fee: bigint,
         createdAtTime: [bigint] | []
@@ -49,8 +51,8 @@ export default class {
         });
     }
 
-    @update([Address], Tokens)
-    async getAccountBalance(address: Address): Promise<Tokens> {
+    @update([IDL.Text], Tokens)
+    async getAccountBalance(address: string): Promise<Tokens> {
         return await call(getIcpCanisterPrincipal(), 'account_balance', {
             paramIdlTypes: [AccountBalanceArgs],
             returnIdlType: Tokens,