Created
September 23, 2021 03:47
-
-
Save shanev/62acb3c7f38fb99d25fcc5939b3c1afd to your computer and use it in GitHub Desktop.
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
/* | |
* Wraps a cw721 contract with helpers. | |
* Adapted from https://github.com/CosmWasm/cw-plus/blob/main/contracts/cw721-base/helpers.ts. | |
*/ | |
import { | |
CosmWasmClient, | |
SigningCosmWasmClient, | |
} from '@cosmjs/cosmwasm-stargate'; | |
import { coins } from '@cosmjs/stargate'; | |
export const defaultExecuteFee = { | |
amount: coins(3000, process.env.NEXT_PUBLIC_DEFAULT_GAS_DENOM || 'ustarx'), | |
gas: process.env.NEXT_PUBLIC_DEFAULT_GAS_FEE || '333333', | |
}; | |
export type TokenId = string; | |
export interface Balances { | |
readonly address: string; | |
readonly amount: string; // decimal as string | |
} | |
export interface MintInfo { | |
readonly minter: string; | |
readonly cap?: string; // decimal as string | |
} | |
export interface ContractInfo { | |
readonly name: string; | |
readonly symbol: string; | |
} | |
export interface NftInfo { | |
readonly name: string; | |
readonly description: string; | |
readonly image: any; | |
} | |
export interface Access { | |
readonly owner: string; | |
readonly approvals: []; | |
} | |
export interface AllNftInfo { | |
readonly access: Access; | |
readonly info: NftInfo; | |
} | |
export interface Operators { | |
readonly operators: []; | |
} | |
export interface Count { | |
readonly count: number; | |
} | |
// Better to use this interface? | |
export interface MintMsg { | |
readonly token_id: TokenId; | |
readonly owner: string; | |
readonly name: string; | |
readonly description?: string; | |
readonly image?: string; | |
} | |
export type Expiration = | |
| { readonly at_height: number } | |
| { readonly at_time: number } | |
| { readonly never: {} }; | |
export interface AllowanceResponse { | |
readonly allowance: string; // integer as string | |
readonly expires: Expiration; | |
} | |
export interface AllowanceInfo { | |
readonly allowance: string; // integer as string | |
readonly spender: string; // bech32 address | |
readonly expires: Expiration; | |
} | |
export interface AllAllowancesResponse { | |
readonly allowances: readonly AllowanceInfo[]; | |
} | |
export interface AllAccountsResponse { | |
// list of bech32 address that have a balance | |
readonly accounts: readonly string[]; | |
} | |
export interface TokensResponse { | |
readonly tokens: readonly string[]; | |
} | |
export interface CW721ReadOnlyInstance { | |
readonly contractAddress: string; | |
// queries | |
allowance: (owner: string, spender: string) => Promise<AllowanceResponse>; | |
allAllowances: ( | |
owner: string, | |
startAfter?: string, | |
limit?: number | |
) => Promise<AllAllowancesResponse>; | |
allAccounts: ( | |
startAfter?: string, | |
limit?: number | |
) => Promise<readonly string[]>; | |
minter: () => Promise<MintInfo>; | |
contractInfo: () => Promise<ContractInfo>; | |
nftInfo: (tokenId: TokenId) => Promise<NftInfo>; | |
allNftInfo: (tokenId: TokenId) => Promise<AllNftInfo>; | |
ownerOf: (tokenId: TokenId) => Promise<Access>; | |
approvedForAll: ( | |
owner: string, | |
include_expired?: boolean, | |
start_after?: string, | |
limit?: number | |
) => Promise<Operators>; | |
numTokens: () => Promise<Count>; | |
tokens: ( | |
owner: string, | |
startAfter?: string, | |
limit?: number | |
) => Promise<TokensResponse>; | |
allTokens: (startAfter?: string, limit?: number) => Promise<TokensResponse>; | |
} | |
export interface CW721Instance extends CW721ReadOnlyInstance { | |
// actions | |
mint: ( | |
sender: string, | |
tokenId: TokenId, | |
owner: string, | |
name: string, | |
level: number, | |
description?: string, | |
image?: string | |
) => Promise<string>; | |
transferNft: ( | |
sender: string, | |
recipient: string, | |
tokenId: TokenId | |
) => Promise<string>; | |
sendNft: ( | |
sender: string, | |
contract: string, | |
token_id: TokenId, | |
msg?: BinaryType | |
) => Promise<string>; | |
approve: ( | |
spender: string, | |
tokenId: TokenId, | |
expires?: Expiration | |
) => Promise<string>; | |
approveAll: ( | |
sender: string, | |
operator: string, | |
expires?: Expiration | |
) => Promise<string>; | |
revoke: (spender: string, tokenId: TokenId) => Promise<string>; | |
revokeAll: (sender: string, operator: string) => Promise<string>; | |
} | |
interface CW721Contract { | |
use: (contractAddress: string) => CW721Instance | CW721ReadOnlyInstance; | |
} | |
export const CW721 = ( | |
client: SigningCosmWasmClient | CosmWasmClient | |
): CW721Contract => { | |
const use = ( | |
contractAddress: string | |
): CW721Instance | CW721ReadOnlyInstance => { | |
// queries | |
const allowance = async ( | |
owner: string, | |
spender: string | |
): Promise<AllowanceResponse> => { | |
return client.queryContractSmart(contractAddress, { | |
allowance: { owner, spender }, | |
}); | |
}; | |
const allAllowances = async ( | |
owner: string, | |
startAfter?: string, | |
limit?: number | |
): Promise<AllAllowancesResponse> => { | |
return client.queryContractSmart(contractAddress, { | |
all_allowances: { owner, start_after: startAfter, limit }, | |
}); | |
}; | |
const allAccounts = async ( | |
startAfter?: string, | |
limit?: number | |
): Promise<readonly string[]> => { | |
const accounts: AllAccountsResponse = await client.queryContractSmart( | |
contractAddress, | |
{ all_accounts: { start_after: startAfter, limit } } | |
); | |
return accounts.accounts; | |
}; | |
const minter = async (): Promise<MintInfo> => { | |
return client.queryContractSmart(contractAddress, { minter: {} }); | |
}; | |
const contractInfo = async (): Promise<ContractInfo> => { | |
return client.queryContractSmart(contractAddress, { contract_info: {} }); | |
}; | |
const nftInfo = async (token_id: TokenId): Promise<NftInfo> => { | |
return client.queryContractSmart(contractAddress, { | |
nft_info: { token_id }, | |
}); | |
}; | |
const allNftInfo = async (token_id: TokenId): Promise<AllNftInfo> => { | |
return client.queryContractSmart(contractAddress, { | |
all_nft_info: { token_id }, | |
}); | |
}; | |
const ownerOf = async (token_id: TokenId): Promise<Access> => { | |
return await client.queryContractSmart(contractAddress, { | |
owner_of: { token_id }, | |
}); | |
}; | |
const approvedForAll = async ( | |
owner: string, | |
include_expired?: boolean, | |
start_after?: string, | |
limit?: number | |
): Promise<Operators> => { | |
return await client.queryContractSmart(contractAddress, { | |
approved_for_all: { owner, include_expired, start_after, limit }, | |
}); | |
}; | |
// total number of tokens issued | |
const numTokens = async (): Promise<Count> => { | |
return client.queryContractSmart(contractAddress, { num_tokens: {} }); | |
}; | |
// list all token_ids that belong to a given owner | |
const tokens = async ( | |
owner: string, | |
start_after?: string, | |
limit?: number | |
): Promise<TokensResponse> => { | |
return client.queryContractSmart(contractAddress, { | |
tokens: { owner, start_after, limit }, | |
}); | |
}; | |
const allTokens = async ( | |
start_after?: string, | |
limit?: number | |
): Promise<TokensResponse> => { | |
return client.queryContractSmart(contractAddress, { | |
all_tokens: { start_after, limit }, | |
}); | |
}; | |
// actions | |
if (client instanceof SigningCosmWasmClient) { | |
const mint = async ( | |
sender: string, | |
token_id: TokenId, | |
owner: string, | |
name: string, | |
level: number, | |
description?: string, | |
image?: string | |
): Promise<string> => { | |
const result = await client.execute( | |
sender, | |
contractAddress, | |
{ | |
mint: { token_id, owner, name, level, description, image }, | |
}, | |
defaultExecuteFee | |
); | |
return result.transactionHash; | |
}; | |
// transfers ownership, returns transactionHash | |
const transferNft = async ( | |
sender: string, | |
recipient: string, | |
token_id: TokenId | |
): Promise<string> => { | |
const result = await client.execute( | |
sender, | |
contractAddress, | |
{ | |
transfer_nft: { recipient, token_id }, | |
}, | |
defaultExecuteFee | |
); | |
return result.transactionHash; | |
}; | |
// sends an nft token to another contract (TODO: msg type any needs to be revisited once receiveNft is implemented) | |
const sendNft = async ( | |
sender: string, | |
contract: string, | |
token_id: TokenId, | |
msg?: any | |
): Promise<string> => { | |
const result = await client.execute( | |
sender, | |
contractAddress, | |
{ | |
send_nft: { contract, token_id, msg }, | |
}, | |
defaultExecuteFee | |
); | |
return result.transactionHash; | |
}; | |
const approve = async ( | |
spender: string, | |
token_id: TokenId, | |
expires?: Expiration | |
): Promise<string> => { | |
const result = await client.execute( | |
spender, | |
contractAddress, | |
{ | |
approve: { spender, token_id, expires }, | |
}, | |
defaultExecuteFee | |
); | |
return result.transactionHash; | |
}; | |
const approveAll = async ( | |
sender: string, | |
operator: string, | |
expires?: Expiration | |
): Promise<string> => { | |
const result = await client.execute( | |
sender, | |
contractAddress, | |
{ | |
approve_all: { operator, expires }, | |
}, | |
defaultExecuteFee | |
); | |
return result.transactionHash; | |
}; | |
const revoke = async ( | |
spender: string, | |
token_id: TokenId | |
): Promise<string> => { | |
const result = await client.execute( | |
spender, | |
contractAddress, | |
{ | |
revoke: { spender, token_id }, | |
}, | |
defaultExecuteFee | |
); | |
return result.transactionHash; | |
}; | |
const revokeAll = async ( | |
sender: string, | |
operator: string | |
): Promise<string> => { | |
const result = await client.execute( | |
sender, | |
contractAddress, | |
{ | |
revoke_all: { operator }, | |
}, | |
defaultExecuteFee | |
); | |
return result.transactionHash; | |
}; | |
return { | |
contractAddress, | |
allowance, | |
allAllowances, | |
allAccounts, | |
minter, | |
contractInfo, | |
nftInfo, | |
allNftInfo, | |
ownerOf, | |
approvedForAll, | |
numTokens, | |
tokens, | |
allTokens, | |
mint, | |
transferNft, | |
sendNft, | |
approve, | |
approveAll, | |
revoke, | |
revokeAll, | |
}; | |
} | |
return { | |
contractAddress, | |
allowance, | |
allAllowances, | |
allAccounts, | |
minter, | |
contractInfo, | |
nftInfo, | |
allNftInfo, | |
ownerOf, | |
approvedForAll, | |
numTokens, | |
tokens, | |
allTokens, | |
}; | |
}; | |
return { use }; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment