Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Storage Management contract standards functions #1386

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion packages/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@
"@near-js/types": "workspace:*",
"@near-js/utils": "workspace:*",
"@noble/hashes": "1.3.3",
"isomorphic-fetch": "3.0.0"
"isomorphic-fetch": "3.0.0",
"near-contract-standards": "^2.0.0",
"near-ledger-js": "0.2.1",
"near-sdk-js": "^2.0.0"
},
"keywords": [],
"author": "",
Expand Down
117 changes: 117 additions & 0 deletions packages/client/src/contract-standards/fungible-token.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import { functionCall } from "../transactions/actions";
import type {
FungibleTokenMetadata,
FungibleTokenMetadataProvider,
FungibleTokenCore,
} from "near-contract-standards/lib";
import type { FunctionCallParams, ViewParams } from "../interfaces";
import type { FinalExecutionOutcome } from "@near-js/types";
import { view } from "../view";

type FungibleTokenParams<T extends keyof (FungibleTokenCore)> = Omit<
FunctionCallParams,
"method" | "args"
> & {
args: Parameters<(FungibleTokenCore)[T]>[0];
};

type FungibleTokenViewParams<T extends keyof (FungibleTokenCore & FungibleTokenMetadataProvider)> = Omit<
ViewParams,
"method" | "args"
> & {
args: Parameters<(FungibleTokenCore & FungibleTokenMetadataProvider)[T]>[0];
};

type FungibleTokenReturn<T extends keyof (FungibleTokenCore)> = {
outcome: FinalExecutionOutcome;
result: ReturnType<(FungibleTokenCore)[T]>;
};

type FungibleTokenViewReturn<T extends keyof (FungibleTokenCore & FungibleTokenMetadataProvider)> =
ReturnType<(FungibleTokenCore & FungibleTokenMetadataProvider)[T]>;

export async function ftTransfer(
params: FungibleTokenParams<"ft_transfer">
): Promise<FungibleTokenReturn<"ft_transfer">> {
// bigints go over the wire as strings
const {args, ...otherParams} = params;
const convertedArgs = {
...args,
amount: args.amount ? args.amount.toString() : undefined,
};
const { outcome } = await functionCall({
args: convertedArgs,
...otherParams,
method: "ft_transfer",
deposit: 1n,
});

return {
outcome,
result: undefined,
};
}

/**
* TODO This function is untested
*/
export async function ftTransferCall(
params: FungibleTokenParams<"ft_transfer_call">
): Promise<FungibleTokenReturn<"ft_transfer_call">> {
// bigints go over the wire as strings
const {args, ...otherParams} = params;
const convertedArgs = {
...args,
amount: args.amount ? args.amount.toString() : undefined,
};
const { outcome, result } = await functionCall({
args: convertedArgs,
...otherParams,
method: "ft_transfer_call",
deposit: 1n,
});

return {
outcome,
// result: result as string,
result: BigInt(result as string),
};
}

export async function ftTotalSupply(
params: FungibleTokenViewParams<"ft_total_supply">
): Promise<FungibleTokenViewReturn<"ft_total_supply">> {
const result = await view({
...params,
method: "ft_total_supply",
});

return BigInt(result as string);
}

export async function ftBalanceOf(
params: FungibleTokenViewParams<"ft_balance_of">
): Promise<FungibleTokenViewReturn<"ft_balance_of">> {
const result = await view({
...params,
method: "ft_balance_of",
});

return BigInt(result as string);
}

/**
* Fungible Token Metadata is techically a separate NEP standard, but it's
* included here for convenience
* NEP: https://github.com/near/NEPs/blob/master/neps/nep-0148.md
*/
export async function ftMetadata(
params: FungibleTokenViewParams<"ft_metadata">
): Promise<FungibleTokenViewReturn<"ft_metadata">> {
const result = await view({
...params,
method: "ft_metadata",
});

return result as FungibleTokenMetadata;
}
3 changes: 3 additions & 0 deletions packages/client/src/contract-standards/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './storage-management';
export * from './fungible-token';
export * from './non-fungible-token';
191 changes: 191 additions & 0 deletions packages/client/src/contract-standards/non-fungible-token.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
import { functionCall } from "../transactions/actions";
import type {
NonFungibleTokenCore,
NonFungibleTokenEnumeration,
NonFungibleTokenMetadataProvider,
NFTContractMetadata,
// TokenMetadata,
Token
} from "near-contract-standards/lib";
import type {
FunctionCallParams,
ViewParams
} from "../interfaces";
import type { FinalExecutionOutcome } from "@near-js/types";
import { view } from "../view";

type NFTParams<T extends keyof (NonFungibleTokenCore)> = Omit<
FunctionCallParams,
"method" | "args"
> & {
args: Parameters<(NonFungibleTokenCore)[T]>[0];
};

type NFTViewParams<T extends keyof (NonFungibleTokenCore & NonFungibleTokenEnumeration & NonFungibleTokenMetadataProvider)> = Omit<
ViewParams,
"method" | "args"
> & {
args: Parameters<(NonFungibleTokenCore & NonFungibleTokenEnumeration & NonFungibleTokenMetadataProvider)[T]>[0];
};

type NFTReturn<T extends keyof (NonFungibleTokenCore)> = {
outcome: FinalExecutionOutcome;
result: ReturnType<(NonFungibleTokenCore)[T]>;
};

type NFTViewReturn<T extends keyof (NonFungibleTokenCore & NonFungibleTokenEnumeration & NonFungibleTokenMetadataProvider)> =
ReturnType<(NonFungibleTokenCore & NonFungibleTokenEnumeration & NonFungibleTokenMetadataProvider)[T]>;

export async function nftTransfer(
params: NFTParams<"nft_transfer">
): Promise<NFTReturn<"nft_transfer">> {
const { outcome } = await functionCall({
...params,
method: "nft_transfer",
deposit: 1n,
});

return {
outcome,
result: undefined,
};
}

/**
* TODO This function is untested
*/
export async function nftTransferCall(
params: NFTParams<"nft_transfer_call">
): Promise<NFTReturn<"nft_transfer_call">> {
const { outcome, result } = await functionCall({
...params,
method: "nft_transfer_call",
deposit: 1n,
});

return {
outcome,
result: result as string,
};
}

export async function nftToken(
params: NFTViewParams<"nft_token">
): Promise<NFTViewReturn<"nft_token">> {
const result = await view({
...params,
method: "nft_token",
});

return result as Token;
}

// ! NOTE: according to the NEP, this function should return a string but
// ! the contract standards lib incorrectly implements it as a number, therefore
// ! we break from usage of the lib and implement our own return type. We expect
// ! a string then cast to bigint for convenience
export async function nftTotalSupply(
params: NFTViewParams<"nft_total_supply">
): Promise<bigint> {
const result = await view({
...params,
method: "nft_total_supply",
});

if (typeof result === "string" || typeof result === "number") {
// technically we shouldn't allow number, but we will allow it in case
// the contract is built against the incorrect near-sdk-js spec
try {
const bi = BigInt(result);
return bi;
} catch (e) {
throw new Error("nft_total_supply result could not be converted to bigint");
}
}
throw new Error("nft_total_supply did not return a string or number");
}

// ! NOTE: according to the NEP, this function should return a string but
// ! the contract standards lib incorrectly implements it as a number, therefore
// ! we break from usage of the lib and implement our own return type. We expect
// ! a string then cast to bigint for convenience
export async function nftSupplyForOwner(
params: NFTViewParams<"nft_supply_for_owner">
): Promise<bigint> {
const result = await view({
...params,
method: "nft_supply_for_owner",
});

if (typeof result === "string" || typeof result === "number") {
// technically we shouldn't allow number, but we will allow it in case
// the contract is built against the incorrect near-sdk-js spec
try {
const bi = BigInt(result);
return bi;
} catch (e) {
throw new Error("nft_supply_for_owner result could not be converted to bigint");
}
}
throw new Error("nft_supply_for_owner did not return a string or number");
}

// ! Convert `from_index` to bigint | null to match the NEP
type NFTTokensParams = Omit<NFTViewParams<"nft_tokens">, "args"> & {
args: Omit<NFTViewParams<"nft_tokens">["args"], "from_index"> & {
from_index: bigint | null;
};
};
export async function nftTokens(
params: NFTTokensParams
): Promise<NFTViewReturn<"nft_tokens">> {
// bigints go over the wire as strings
const {args, ...otherParams} = params;
const convertedArgs = {
...args,
from_index: args.from_index ? args.from_index.toString() : null,
};
const result = await view({
args: convertedArgs,
...otherParams,
method: "nft_tokens",
});

return result as Token[];
}

// ! Convert `from_index` to bigint | null to match the NEP
type NFTTokensForOwnerParams = Omit<NFTViewParams<"nft_tokens_for_owner">, "args"> & {
args: Omit<NFTViewParams<"nft_tokens_for_owner">["args"], "from_index"> & {
from_index: bigint | null;
};
};

export async function nftTokensForOwner(
params: NFTTokensForOwnerParams
): Promise<NFTViewReturn<"nft_tokens_for_owner">> {
// bigints go over the wire as strings
const {args, ...otherParams} = params;
const convertedArgs = {
...args,
from_index: args.from_index ? args.from_index.toString() : null,
};
const result = await view({
args: convertedArgs,
...otherParams,
method: "nft_tokens_for_owner",
});

return result as Token[];
}

export async function nftMetadata(
params: NFTViewParams<"nft_metadata">
): Promise<NFTViewReturn<"nft_metadata">> {
const result = await view({
...params,
method: "nft_metadata",
});

return result as NFTContractMetadata;
}
Loading
Loading