-
Notifications
You must be signed in to change notification settings - Fork 244
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: client interfaces for interacting with NEP standard contracts
- Loading branch information
Showing
14 changed files
with
2,570 additions
and
51 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
--- | ||
"@near-js/client": minor | ||
"@near-js/cookbook": minor | ||
--- | ||
|
||
Introduce interfaces for interacting with contracts which implement certain NEP standards |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
122 changes: 122 additions & 0 deletions
122
packages/client/src/contract-standards/fungible-token.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
/** | ||
* Interface for Fungible Token contracts covering the following standards: | ||
* - Fungible Token Standard: https://github.com/near/NEPs/blob/master/neps/nep-0141.md | ||
* - Fungible Token Metadata: https://github.com/near/NEPs/blob/master/neps/nep-0148.md | ||
*/ | ||
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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'; |
194 changes: 194 additions & 0 deletions
194
packages/client/src/contract-standards/non-fungible-token.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,194 @@ | ||
/** | ||
* Interface for Non-Fungible Token contracts covering the following standards: | ||
* - Non Fungible Token Standard: https://github.com/near/NEPs/blob/master/neps/nep-0171.md | ||
* - Non Fungible Token Metadata: https://github.com/near/NEPs/blob/master/neps/nep-0177.md | ||
* - Non Fungible Token Enumeration: https://github.com/near/NEPs/blob/master/neps/nep-0181.md | ||
*/ | ||
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, | ||
}; | ||
} | ||
|
||
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; | ||
} |
Oops, something went wrong.