Implement contract UIs (#2)
* Add instantiate page for minter * Add query page to minter contract * Add execute page for minter contract * Add contracts index page * Refaactor sg721 helper files * Add instantiate page * Add query page for sg721 * Add execute page for sg721 contract * Copy page templates for whitelist contracts * Add instantitate for whitelist contract * Add query page to whitelist contract * Add execute page for whitelist contract
This commit is contained in:
+251
-63
@@ -1,7 +1,8 @@
|
||||
import { SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate'
|
||||
import { Coin } from '@cosmjs/proto-signing'
|
||||
import { logs } from '@cosmjs/stargate'
|
||||
import { Timestamp } from '@stargazezone/types/contracts/minter/shared-types'
|
||||
import type { SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate'
|
||||
import type { Coin } from '@cosmjs/proto-signing'
|
||||
import { coin } from '@cosmjs/proto-signing'
|
||||
import type { logs } from '@cosmjs/stargate'
|
||||
import type { Timestamp } from '@stargazezone/types/contracts/minter/shared-types'
|
||||
|
||||
export interface InstantiateResponse {
|
||||
readonly contractAddress: string
|
||||
@@ -9,7 +10,7 @@ export interface InstantiateResponse {
|
||||
readonly logs: readonly logs.Log[]
|
||||
}
|
||||
|
||||
export type RoyalityInfo = {
|
||||
export interface RoyalityInfo {
|
||||
payment_address: string
|
||||
share: string
|
||||
}
|
||||
@@ -25,22 +26,108 @@ export interface MinterInstance {
|
||||
getMintCount: (address: string) => Promise<any>
|
||||
|
||||
//Execute
|
||||
mint: (senderAddress: string) => Promise<string>
|
||||
mint: (senderAddress: string, price: string) => Promise<string>
|
||||
setWhitelist: (senderAddress: string, whitelist: string) => Promise<string>
|
||||
updateStartTime: (senderAddress: string, time: Timestamp) => Promise<string>
|
||||
updatePerAddressLimit: (
|
||||
senderAddress: string,
|
||||
per_address_limit: number
|
||||
) => Promise<string>
|
||||
updatePerAddressLimit: (senderAddress: string, perAddressLimit: number) => Promise<string>
|
||||
mintTo: (senderAddress: string, recipient: string) => Promise<string>
|
||||
mintFor: (
|
||||
senderAddress: string,
|
||||
token_id: number,
|
||||
recipient: string
|
||||
) => Promise<string>
|
||||
mintFor: (senderAddress: string, recipient: string, tokenId: number) => Promise<string>
|
||||
shuffle: (senderAddress: string) => Promise<string>
|
||||
withdraw: (senderAddress: string) => Promise<string>
|
||||
}
|
||||
|
||||
export interface MinterMessages {
|
||||
mint: (contractAddress: string, price: string) => MintMessage
|
||||
setWhitelist: (contractAddress: string, whitelist: string) => SetWhitelistMessage
|
||||
updateStartTime: (contractAddress: string, time: Timestamp) => UpdateStarTimeMessage
|
||||
updatePerAddressLimit: (contractAddress: string, perAddressLimit: number) => UpdatePerAddressLimitMessage
|
||||
mintTo: (contractAddress: string, recipient: string) => MintToMessage
|
||||
mintFor: (contractAddress: string, recipient: string, tokenId: number) => MintForMessage
|
||||
shuffle: (contractAddress: string) => ShuffleMessage
|
||||
withdraw: (contractAddress: string) => WithdrawMessage
|
||||
}
|
||||
|
||||
export interface MintMessage {
|
||||
sender: string
|
||||
contract: string
|
||||
msg: {
|
||||
mint: Record<string, never>
|
||||
}
|
||||
funds: Coin[]
|
||||
}
|
||||
|
||||
export interface SetWhitelistMessage {
|
||||
sender: string
|
||||
contract: string
|
||||
msg: {
|
||||
set_whitelist: {
|
||||
whitelist: string
|
||||
}
|
||||
}
|
||||
funds: Coin[]
|
||||
}
|
||||
|
||||
export interface UpdateStarTimeMessage {
|
||||
sender: string
|
||||
contract: string
|
||||
msg: {
|
||||
update_start_time: string
|
||||
}
|
||||
funds: Coin[]
|
||||
}
|
||||
|
||||
export interface UpdatePerAddressLimitMessage {
|
||||
sender: string
|
||||
contract: string
|
||||
msg: {
|
||||
update_per_address_limit: {
|
||||
per_address_limit: number
|
||||
}
|
||||
}
|
||||
funds: Coin[]
|
||||
}
|
||||
|
||||
export interface MintToMessage {
|
||||
sender: string
|
||||
contract: string
|
||||
msg: {
|
||||
mint_to: {
|
||||
recipient: string
|
||||
}
|
||||
}
|
||||
funds: Coin[]
|
||||
}
|
||||
|
||||
export interface MintForMessage {
|
||||
sender: string
|
||||
contract: string
|
||||
msg: {
|
||||
mint_for: {
|
||||
recipient: string
|
||||
token_id: number
|
||||
}
|
||||
}
|
||||
funds: Coin[]
|
||||
}
|
||||
|
||||
export interface ShuffleMessage {
|
||||
sender: string
|
||||
contract: string
|
||||
msg: {
|
||||
shuffle: Record<string, never>
|
||||
}
|
||||
funds: Coin[]
|
||||
}
|
||||
|
||||
export interface WithdrawMessage {
|
||||
sender: string
|
||||
contract: string
|
||||
msg: {
|
||||
withdraw: Record<string, never>
|
||||
}
|
||||
funds: Coin[]
|
||||
}
|
||||
|
||||
export interface MinterContract {
|
||||
instantiate: (
|
||||
senderAddress: string,
|
||||
@@ -48,13 +135,15 @@ export interface MinterContract {
|
||||
initMsg: Record<string, unknown>,
|
||||
label: string,
|
||||
admin?: string,
|
||||
funds?: Coin[]
|
||||
funds?: Coin[],
|
||||
) => Promise<InstantiateResponse>
|
||||
|
||||
use: (contractAddress: string) => MinterInstance
|
||||
|
||||
messages: () => MinterMessages
|
||||
}
|
||||
|
||||
export const minter = (client: SigningCosmWasmClient): MinterContract => {
|
||||
export const minter = (client: SigningCosmWasmClient, txSigner: string): MinterContract => {
|
||||
const use = (contractAddress: string): MinterInstance => {
|
||||
//Query
|
||||
const getConfig = async (): Promise<any> => {
|
||||
@@ -93,7 +182,7 @@ export const minter = (client: SigningCosmWasmClient): MinterContract => {
|
||||
}
|
||||
|
||||
//Execute
|
||||
const mint = async (senderAddress: string): Promise<string> => {
|
||||
const mint = async (senderAddress: string, price: string): Promise<string> => {
|
||||
const res = await client.execute(
|
||||
senderAddress,
|
||||
contractAddress,
|
||||
@@ -101,16 +190,14 @@ export const minter = (client: SigningCosmWasmClient): MinterContract => {
|
||||
mint: {},
|
||||
},
|
||||
'auto',
|
||||
''
|
||||
'',
|
||||
[coin(price, 'ustars')],
|
||||
)
|
||||
|
||||
return res.transactionHash
|
||||
}
|
||||
|
||||
const setWhitelist = async (
|
||||
senderAddress: string,
|
||||
whitelist: string
|
||||
): Promise<string> => {
|
||||
const setWhitelist = async (senderAddress: string, whitelist: string): Promise<string> => {
|
||||
const res = await client.execute(
|
||||
senderAddress,
|
||||
contractAddress,
|
||||
@@ -118,16 +205,13 @@ export const minter = (client: SigningCosmWasmClient): MinterContract => {
|
||||
set_whitelist: { whitelist },
|
||||
},
|
||||
'auto',
|
||||
''
|
||||
'',
|
||||
)
|
||||
|
||||
return res.transactionHash
|
||||
}
|
||||
|
||||
const updateStartTime = async (
|
||||
senderAddress: string,
|
||||
time: Timestamp
|
||||
): Promise<string> => {
|
||||
const updateStartTime = async (senderAddress: string, time: Timestamp): Promise<string> => {
|
||||
const res = await client.execute(
|
||||
senderAddress,
|
||||
contractAddress,
|
||||
@@ -135,33 +219,27 @@ export const minter = (client: SigningCosmWasmClient): MinterContract => {
|
||||
update_start_time: { time },
|
||||
},
|
||||
'auto',
|
||||
''
|
||||
'',
|
||||
)
|
||||
|
||||
return res.transactionHash
|
||||
}
|
||||
|
||||
const updatePerAddressLimit = async (
|
||||
senderAddress: string,
|
||||
per_address_limit: number
|
||||
): Promise<string> => {
|
||||
const updatePerAddressLimit = async (senderAddress: string, perAddressLimit: number): Promise<string> => {
|
||||
const res = await client.execute(
|
||||
senderAddress,
|
||||
contractAddress,
|
||||
{
|
||||
update_per_address_limit: { per_address_limit },
|
||||
update_per_address_limit: { per_address_limit: perAddressLimit },
|
||||
},
|
||||
'auto',
|
||||
''
|
||||
'',
|
||||
)
|
||||
|
||||
return res.transactionHash
|
||||
}
|
||||
|
||||
const mintTo = async (
|
||||
senderAddress: string,
|
||||
recipient: string
|
||||
): Promise<string> => {
|
||||
const mintTo = async (senderAddress: string, recipient: string): Promise<string> => {
|
||||
const res = await client.execute(
|
||||
senderAddress,
|
||||
contractAddress,
|
||||
@@ -169,25 +247,35 @@ export const minter = (client: SigningCosmWasmClient): MinterContract => {
|
||||
mint_to: { recipient },
|
||||
},
|
||||
'auto',
|
||||
''
|
||||
'',
|
||||
)
|
||||
|
||||
return res.transactionHash
|
||||
}
|
||||
|
||||
const mintFor = async (
|
||||
senderAddress: string,
|
||||
token_id: number,
|
||||
recipient: string
|
||||
): Promise<string> => {
|
||||
const mintFor = async (senderAddress: string, recipient: string, tokenId: number): Promise<string> => {
|
||||
const res = await client.execute(
|
||||
senderAddress,
|
||||
contractAddress,
|
||||
{
|
||||
mint_for: { token_id, recipient },
|
||||
mint_for: { token_id: tokenId, recipient },
|
||||
},
|
||||
'auto',
|
||||
''
|
||||
'',
|
||||
)
|
||||
|
||||
return res.transactionHash
|
||||
}
|
||||
|
||||
const shuffle = async (senderAddress: string): Promise<string> => {
|
||||
const res = await client.execute(
|
||||
senderAddress,
|
||||
contractAddress,
|
||||
{
|
||||
shuffle: {},
|
||||
},
|
||||
'auto',
|
||||
'',
|
||||
)
|
||||
|
||||
return res.transactionHash
|
||||
@@ -201,7 +289,7 @@ export const minter = (client: SigningCosmWasmClient): MinterContract => {
|
||||
withdraw: {},
|
||||
},
|
||||
'auto',
|
||||
''
|
||||
'',
|
||||
)
|
||||
|
||||
return res.transactionHash
|
||||
@@ -220,6 +308,7 @@ export const minter = (client: SigningCosmWasmClient): MinterContract => {
|
||||
updatePerAddressLimit,
|
||||
mintTo,
|
||||
mintFor,
|
||||
shuffle,
|
||||
withdraw,
|
||||
}
|
||||
}
|
||||
@@ -229,21 +318,10 @@ export const minter = (client: SigningCosmWasmClient): MinterContract => {
|
||||
codeId: number,
|
||||
initMsg: Record<string, unknown>,
|
||||
label: string,
|
||||
admin?: string,
|
||||
funds?: Coin[]
|
||||
): Promise<InstantiateResponse> => {
|
||||
console.log(funds)
|
||||
const result = await client.instantiate(
|
||||
senderAddress,
|
||||
codeId,
|
||||
initMsg,
|
||||
label,
|
||||
'auto',
|
||||
{
|
||||
funds,
|
||||
admin,
|
||||
}
|
||||
)
|
||||
const result = await client.instantiate(senderAddress, codeId, initMsg, label, 'auto', {
|
||||
funds: [coin('1000000000', 'ustars')],
|
||||
})
|
||||
|
||||
return {
|
||||
contractAddress: result.contractAddress,
|
||||
@@ -252,5 +330,115 @@ export const minter = (client: SigningCosmWasmClient): MinterContract => {
|
||||
}
|
||||
}
|
||||
|
||||
return { use, instantiate }
|
||||
const messages = () => {
|
||||
const mint = (contractAddress: string, price: string): MintMessage => {
|
||||
return {
|
||||
sender: txSigner,
|
||||
contract: contractAddress,
|
||||
msg: {
|
||||
mint: {},
|
||||
},
|
||||
funds: [coin(price, 'ustars')],
|
||||
}
|
||||
}
|
||||
|
||||
const setWhitelist = (contractAddress: string, whitelist: string): SetWhitelistMessage => {
|
||||
return {
|
||||
sender: txSigner,
|
||||
contract: contractAddress,
|
||||
msg: {
|
||||
set_whitelist: {
|
||||
whitelist,
|
||||
},
|
||||
},
|
||||
funds: [],
|
||||
}
|
||||
}
|
||||
|
||||
const updateStartTime = (contractAddress: string, startTime: string): UpdateStarTimeMessage => {
|
||||
return {
|
||||
sender: txSigner,
|
||||
contract: contractAddress,
|
||||
msg: {
|
||||
update_start_time: startTime,
|
||||
},
|
||||
funds: [],
|
||||
}
|
||||
}
|
||||
|
||||
const updatePerAddressLimit = (contractAddress: string, limit: number): UpdatePerAddressLimitMessage => {
|
||||
return {
|
||||
sender: txSigner,
|
||||
contract: contractAddress,
|
||||
msg: {
|
||||
update_per_address_limit: {
|
||||
per_address_limit: limit,
|
||||
},
|
||||
},
|
||||
funds: [],
|
||||
}
|
||||
}
|
||||
|
||||
const mintTo = (contractAddress: string, recipient: string): MintToMessage => {
|
||||
return {
|
||||
sender: txSigner,
|
||||
contract: contractAddress,
|
||||
msg: {
|
||||
mint_to: {
|
||||
recipient,
|
||||
},
|
||||
},
|
||||
funds: [],
|
||||
}
|
||||
}
|
||||
|
||||
const mintFor = (contractAddress: string, recipient: string, tokenId: number): MintForMessage => {
|
||||
return {
|
||||
sender: txSigner,
|
||||
contract: contractAddress,
|
||||
msg: {
|
||||
mint_for: {
|
||||
recipient,
|
||||
token_id: tokenId,
|
||||
},
|
||||
},
|
||||
funds: [],
|
||||
}
|
||||
}
|
||||
|
||||
const shuffle = (contractAddress: string): ShuffleMessage => {
|
||||
return {
|
||||
sender: txSigner,
|
||||
contract: contractAddress,
|
||||
msg: {
|
||||
shuffle: {},
|
||||
},
|
||||
funds: [],
|
||||
}
|
||||
}
|
||||
|
||||
const withdraw = (contractAddress: string): WithdrawMessage => {
|
||||
return {
|
||||
sender: txSigner,
|
||||
contract: contractAddress,
|
||||
msg: {
|
||||
withdraw: {},
|
||||
},
|
||||
funds: [],
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
mint,
|
||||
setWhitelist,
|
||||
updateStartTime,
|
||||
updatePerAddressLimit,
|
||||
mintTo,
|
||||
mintFor,
|
||||
shuffle,
|
||||
withdraw,
|
||||
}
|
||||
}
|
||||
|
||||
return { use, instantiate, messages }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
import type { MinterInstance } from '../index'
|
||||
import { useMinterContract } from '../index'
|
||||
|
||||
export type ExecuteType = typeof EXECUTE_TYPES[number]
|
||||
|
||||
export const EXECUTE_TYPES = [
|
||||
'mint',
|
||||
'set_whitelist',
|
||||
'update_start_time',
|
||||
'update_per_address_limit',
|
||||
'mint_to',
|
||||
'mint_for',
|
||||
'shuffle',
|
||||
'withdraw',
|
||||
] as const
|
||||
|
||||
export interface ExecuteListItem {
|
||||
id: ExecuteType
|
||||
name: string
|
||||
description?: string
|
||||
}
|
||||
|
||||
export const EXECUTE_LIST: ExecuteListItem[] = [
|
||||
{
|
||||
id: 'mint',
|
||||
name: 'Mint',
|
||||
description: `Mint new tokens for a given address`,
|
||||
},
|
||||
{
|
||||
id: 'set_whitelist',
|
||||
name: 'Set Whitelist',
|
||||
description: `Set whitelist contract address`,
|
||||
},
|
||||
{
|
||||
id: 'update_start_time',
|
||||
name: 'Update Start Time',
|
||||
description: `Update start time for minting`,
|
||||
},
|
||||
{
|
||||
id: 'update_per_address_limit',
|
||||
name: 'Update Per Address Limit',
|
||||
description: `Update token per address limit`,
|
||||
},
|
||||
{
|
||||
id: 'mint_to',
|
||||
name: 'Mint To',
|
||||
description: `Mint tokens to a given address`,
|
||||
},
|
||||
{
|
||||
id: 'mint_for',
|
||||
name: 'Mint For',
|
||||
description: `Mint tokens for a given address with a given token ID`,
|
||||
},
|
||||
{
|
||||
id: 'shuffle',
|
||||
name: 'Shuffle',
|
||||
description: `Shuffle the token IDs`,
|
||||
},
|
||||
]
|
||||
|
||||
export interface DispatchExecuteProps {
|
||||
type: ExecuteType
|
||||
[k: string]: unknown
|
||||
}
|
||||
|
||||
type Select<T extends ExecuteType> = T
|
||||
|
||||
/** @see {@link MinterInstance} */
|
||||
export type DispatchExecuteArgs = {
|
||||
contract: string
|
||||
messages?: MinterInstance
|
||||
txSigner: string
|
||||
} & (
|
||||
| { type: undefined }
|
||||
| { type: Select<'mint'>; price: string }
|
||||
| { type: Select<'set_whitelist'>; whitelist: string }
|
||||
| { type: Select<'update_start_time'>; startTime: string }
|
||||
| { type: Select<'update_per_address_limit'>; limit: number }
|
||||
| { type: Select<'mint_to'>; recipient: string }
|
||||
| { type: Select<'mint_for'>; recipient: string; tokenId: number }
|
||||
| { type: Select<'shuffle'> }
|
||||
| { type: Select<'withdraw'> }
|
||||
)
|
||||
|
||||
export const dispatchExecute = async (args: DispatchExecuteArgs) => {
|
||||
const { messages, txSigner } = args
|
||||
if (!messages) {
|
||||
throw new Error('cannot dispatch execute, messages is not defined')
|
||||
}
|
||||
switch (args.type) {
|
||||
case 'mint': {
|
||||
return messages.mint(txSigner, args.price === '' ? '0' : args.price)
|
||||
}
|
||||
case 'set_whitelist': {
|
||||
return messages.setWhitelist(txSigner, args.whitelist)
|
||||
}
|
||||
case 'update_start_time': {
|
||||
return messages.updateStartTime(txSigner, args.startTime)
|
||||
}
|
||||
case 'update_per_address_limit': {
|
||||
return messages.updatePerAddressLimit(txSigner, args.limit)
|
||||
}
|
||||
case 'mint_to': {
|
||||
return messages.mintTo(txSigner, args.recipient)
|
||||
}
|
||||
case 'mint_for': {
|
||||
return messages.mintFor(txSigner, args.recipient, args.tokenId)
|
||||
}
|
||||
case 'shuffle': {
|
||||
return messages.shuffle(txSigner)
|
||||
}
|
||||
case 'withdraw': {
|
||||
return messages.withdraw(txSigner)
|
||||
}
|
||||
default: {
|
||||
throw new Error('unknown execute type')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const previewExecutePayload = (args: DispatchExecuteArgs) => {
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
const { messages } = useMinterContract()
|
||||
const { contract } = args
|
||||
switch (args.type) {
|
||||
case 'mint': {
|
||||
return messages()?.mint(contract, args.price === '' ? '0' : args.price)
|
||||
}
|
||||
case 'set_whitelist': {
|
||||
return messages()?.setWhitelist(contract, args.whitelist)
|
||||
}
|
||||
case 'update_start_time': {
|
||||
return messages()?.updateStartTime(contract, args.startTime)
|
||||
}
|
||||
case 'update_per_address_limit': {
|
||||
return messages()?.updatePerAddressLimit(contract, args.limit)
|
||||
}
|
||||
case 'mint_to': {
|
||||
return messages()?.mintTo(contract, args.recipient)
|
||||
}
|
||||
case 'mint_for': {
|
||||
return messages()?.mintFor(contract, args.recipient, args.tokenId)
|
||||
}
|
||||
case 'shuffle': {
|
||||
return messages()?.shuffle(contract)
|
||||
}
|
||||
case 'withdraw': {
|
||||
return messages()?.withdraw(contract)
|
||||
}
|
||||
default: {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const isEitherType = <T extends ExecuteType>(type: unknown, arr: T[]): type is T => {
|
||||
return arr.some((val) => type === val)
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
import type { MinterInstance } from '../contract'
|
||||
|
||||
export type QueryType = typeof QUERY_TYPES[number]
|
||||
|
||||
export const QUERY_TYPES = ['config', 'mintable_num_tokens', 'start_time', 'mint_price', 'mint_count'] as const
|
||||
|
||||
export interface QueryListItem {
|
||||
id: QueryType
|
||||
name: string
|
||||
description?: string
|
||||
}
|
||||
|
||||
export const QUERY_LIST: QueryListItem[] = [
|
||||
{ id: 'config', name: 'Config', description: 'View current config' },
|
||||
{ id: 'mintable_num_tokens', name: 'Total Mintable Tokens', description: 'View the total amount of mintable tokens' },
|
||||
{ id: 'start_time', name: 'Start Time', description: 'View the start time for minting' },
|
||||
{ id: 'mint_price', name: 'Mint Price', description: 'View the mint price' },
|
||||
{
|
||||
id: 'mint_count',
|
||||
name: 'Total Minted Count',
|
||||
description: 'View the total amount of minted tokens for an address',
|
||||
},
|
||||
]
|
||||
|
||||
export interface DispatchQueryProps {
|
||||
address: string
|
||||
messages: MinterInstance | undefined
|
||||
type: QueryType
|
||||
}
|
||||
|
||||
export const dispatchQuery = (props: DispatchQueryProps) => {
|
||||
const { address, messages, type } = props
|
||||
switch (type) {
|
||||
case 'config': {
|
||||
return messages?.getConfig()
|
||||
}
|
||||
case 'mintable_num_tokens': {
|
||||
return messages?.getMintableNumTokens()
|
||||
}
|
||||
case 'start_time': {
|
||||
return messages?.getStartTime()
|
||||
}
|
||||
case 'mint_price': {
|
||||
return messages?.getMintPrice()
|
||||
}
|
||||
case 'mint_count': {
|
||||
return messages?.getMintCount(address)
|
||||
}
|
||||
default: {
|
||||
throw new Error('unknown query type')
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,10 @@
|
||||
import { Coin } from '@cosmjs/proto-signing'
|
||||
import { logs } from '@cosmjs/stargate'
|
||||
import type { Coin } from '@cosmjs/proto-signing'
|
||||
import type { logs } from '@cosmjs/stargate'
|
||||
import { useWallet } from 'contexts/wallet'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
|
||||
import {
|
||||
minter as initContract,
|
||||
MinterContract,
|
||||
MinterInstance,
|
||||
} from './contract'
|
||||
import type { MinterContract, MinterInstance, MinterMessages } from './contract'
|
||||
import { minter as initContract } from './contract'
|
||||
|
||||
/*export interface InstantiateResponse {
|
||||
/** The address of the newly instantiated contract *-/
|
||||
@@ -33,11 +30,12 @@ export interface UseMinterContractProps {
|
||||
initMsg: Record<string, unknown>,
|
||||
label: string,
|
||||
admin?: string,
|
||||
funds?: Coin[]
|
||||
funds?: Coin[],
|
||||
) => Promise<InstantiateResponse>
|
||||
use: (customAddress: string) => MinterInstance | undefined
|
||||
updateContractAddress: (contractAddress: string) => void
|
||||
getContractAddress: () => string | undefined
|
||||
messages: () => MinterMessages | undefined
|
||||
}
|
||||
|
||||
export function useMinterContract(): UseMinterContractProps {
|
||||
@@ -52,12 +50,8 @@ export function useMinterContract(): UseMinterContractProps {
|
||||
|
||||
useEffect(() => {
|
||||
if (wallet.initialized) {
|
||||
const getMinterBaseInstance = async (): Promise<void> => {
|
||||
const MinterBaseContract = initContract(wallet.getClient())
|
||||
setMinter(MinterBaseContract)
|
||||
}
|
||||
|
||||
getMinterBaseInstance()
|
||||
const MinterBaseContract = initContract(wallet.getClient(), wallet.address)
|
||||
setMinter(MinterBaseContract)
|
||||
}
|
||||
}, [wallet])
|
||||
|
||||
@@ -66,33 +60,38 @@ export function useMinterContract(): UseMinterContractProps {
|
||||
}
|
||||
|
||||
const instantiate = useCallback(
|
||||
(codeId, initMsg, label, admin?, funds?): Promise<InstantiateResponse> => {
|
||||
(codeId: number, initMsg: Record<string, unknown>, label: string, admin?: string): Promise<InstantiateResponse> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!minter) return reject('Contract is not initialized.')
|
||||
minter
|
||||
.instantiate(wallet.address, codeId, initMsg, label, admin, funds)
|
||||
.then(resolve)
|
||||
.catch(reject)
|
||||
if (!minter) {
|
||||
reject(new Error('Contract is not initialized.'))
|
||||
return
|
||||
}
|
||||
minter.instantiate(wallet.address, codeId, initMsg, label, admin).then(resolve).catch(reject)
|
||||
})
|
||||
},
|
||||
[minter, wallet]
|
||||
[minter, wallet],
|
||||
)
|
||||
|
||||
const use = useCallback(
|
||||
(customAddress = ''): MinterInstance | undefined => {
|
||||
return minter?.use(address || customAddress)
|
||||
},
|
||||
[minter, address]
|
||||
[minter, address],
|
||||
)
|
||||
|
||||
const getContractAddress = (): string | undefined => {
|
||||
return address
|
||||
}
|
||||
|
||||
const messages = useCallback((): MinterMessages | undefined => {
|
||||
return minter?.messages()
|
||||
}, [minter])
|
||||
|
||||
return {
|
||||
instantiate,
|
||||
use,
|
||||
updateContractAddress,
|
||||
getContractAddress,
|
||||
messages,
|
||||
}
|
||||
}
|
||||
|
||||
+348
-201
@@ -1,111 +1,181 @@
|
||||
import { SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate'
|
||||
import { Coin } from '@cosmjs/stargate'
|
||||
import type { SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate'
|
||||
import { toBase64, toUtf8 } from '@cosmjs/encoding'
|
||||
import type { Coin } from '@cosmjs/stargate'
|
||||
import { coin } from '@cosmjs/stargate'
|
||||
|
||||
export interface InstantiateResponse {
|
||||
readonly contractAddress: string
|
||||
readonly transactionHash: string
|
||||
}
|
||||
|
||||
export type Expiration =
|
||||
| { at_height: number }
|
||||
| { at_time: string }
|
||||
| { never: {} }
|
||||
export type Expiration = { at_height: number } | { at_time: string } | { never: Record<string, never> }
|
||||
|
||||
export interface SG721Instance {
|
||||
readonly contractAddress: string
|
||||
|
||||
// queries
|
||||
getOwnerOf: (
|
||||
token_id: string,
|
||||
include_expired: boolean | null
|
||||
) => Promise<any>
|
||||
ownerOf: (tokenId: string, includeExpired?: boolean | null) => Promise<any>
|
||||
|
||||
getApproval: (
|
||||
token_id: string,
|
||||
spender: string,
|
||||
include_expired: boolean | null
|
||||
) => Promise<any>
|
||||
approval: (tokenId: string, spender: string, includeExpired?: boolean | null) => Promise<any>
|
||||
|
||||
getApprovals: (
|
||||
token_id: string,
|
||||
include_expired: boolean | null
|
||||
) => Promise<any>
|
||||
approvals: (tokenId: string, includeExpired?: boolean | null) => Promise<any>
|
||||
|
||||
getAllOperators: (
|
||||
allOperators: (
|
||||
owner: string,
|
||||
include_expired: boolean | null,
|
||||
start_after: string | null,
|
||||
limit: number | null
|
||||
includeExpired?: boolean | null,
|
||||
startAfter?: string | null,
|
||||
limit?: number | null,
|
||||
) => Promise<any>
|
||||
|
||||
getNumTokens: () => Promise<any>
|
||||
numTokens: () => Promise<any>
|
||||
|
||||
getContractInfo: () => Promise<any>
|
||||
contractInfo: () => Promise<any>
|
||||
|
||||
getNftInfo: (token_id: string) => Promise<any>
|
||||
nftInfo: (tokenId: string) => Promise<any>
|
||||
|
||||
getAllNftInfo: (
|
||||
token_id: string,
|
||||
include_expired: boolean | null
|
||||
) => Promise<any>
|
||||
allNftInfo: (tokenId: string, includeExpired?: boolean | null) => Promise<any>
|
||||
|
||||
getTokens: (
|
||||
owner: string,
|
||||
start_after: string | null,
|
||||
limit: number | null
|
||||
) => Promise<any>
|
||||
tokens: (owner: string, startAfter?: string | null, limit?: number | null) => Promise<any>
|
||||
|
||||
getAllTokens: (
|
||||
start_after: string | null,
|
||||
limit: number | null
|
||||
) => Promise<any>
|
||||
allTokens: (startAfter?: string | null, limit?: number | null) => Promise<any>
|
||||
|
||||
getMinter: () => Promise<any>
|
||||
minter: () => Promise<any>
|
||||
|
||||
getCollectionInfo: () => Promise<any>
|
||||
collectionInfo: () => Promise<any>
|
||||
|
||||
//Execute
|
||||
transferNft: (
|
||||
senderAddress: string,
|
||||
recipient: string,
|
||||
token_id: string
|
||||
) => Promise<string>
|
||||
transferNft: (recipient: string, tokenId: string) => Promise<string>
|
||||
/// Send is a base message to transfer a token to a contract and trigger an action
|
||||
/// on the receiving contract.
|
||||
sendNft: (
|
||||
senderAddress: string,
|
||||
contract: string,
|
||||
token_id: string,
|
||||
msg: string //Binary
|
||||
tokenId: string,
|
||||
msg: Record<string, unknown>, //Binary
|
||||
) => Promise<string>
|
||||
/// Allows operator to transfer / send the token from the owner's account.
|
||||
/// If expiration is set, then this allowance has a time/height limit
|
||||
approve: (
|
||||
senderAddress: string,
|
||||
spender: string,
|
||||
token_id: string,
|
||||
expires: Expiration | null
|
||||
) => Promise<string>
|
||||
approve: (spender: string, tokenId: string, expires?: Expiration) => Promise<string>
|
||||
/// Remove previously granted Approval
|
||||
revoke: (
|
||||
senderAddress: string,
|
||||
spender: string,
|
||||
token_id: string
|
||||
) => Promise<string>
|
||||
revoke: (spender: string, tokenId: string) => Promise<string>
|
||||
/// Allows operator to transfer / send any token from the owner's account.
|
||||
/// If expiration is set, then this allowance has a time/height limit
|
||||
approveAll: (
|
||||
senderAddress: string,
|
||||
operator: string,
|
||||
expires: Expiration | null
|
||||
) => Promise<string>
|
||||
approveAll: (operator: string, expires?: Expiration) => Promise<string>
|
||||
/// Remove previously granted ApproveAll permission
|
||||
revokeAll: (senderAddress: string, operator: string) => Promise<string>
|
||||
revokeAll: (operator: string) => Promise<string>
|
||||
/// Mint a new NFT, can only be called by the contract minter
|
||||
mint: (senderAddress: string, msg: string) => Promise<string> //MintMsg<T>
|
||||
mint: (tokenId: string, owner: string, tokenURI?: string) => Promise<string> //MintMsg<T>
|
||||
|
||||
/// Burn an NFT the sender has access to
|
||||
burn: (senderAddress: string, token_id: string) => Promise<string>
|
||||
burn: (tokenId: string) => Promise<string>
|
||||
}
|
||||
|
||||
export interface Sg721Messages {
|
||||
transferNft: (recipient: string, tokenId: string) => TransferNFTMessage
|
||||
sendNft: (contract: string, tokenId: string, msg: Record<string, unknown>) => SendNFTMessage
|
||||
approve: (recipient: string, tokenId: string, expires?: Expiration) => ApproveMessage
|
||||
revoke: (recipient: string, tokenId: string) => RevokeMessage
|
||||
approveAll: (operator: string, expires?: Expiration) => ApproveAllMessage
|
||||
revokeAll: (operator: string) => RevokeAllMessage
|
||||
mint: (tokenId: string, owner: string, tokenURI?: string) => MintMessage
|
||||
burn: (tokenId: string) => BurnMessage
|
||||
}
|
||||
|
||||
export interface TransferNFTMessage {
|
||||
sender: string
|
||||
contract: string
|
||||
msg: {
|
||||
transfer_nft: {
|
||||
recipient: string
|
||||
token_id: string
|
||||
}
|
||||
}
|
||||
funds: Coin[]
|
||||
}
|
||||
|
||||
export interface SendNFTMessage {
|
||||
sender: string
|
||||
contract: string
|
||||
msg: {
|
||||
send_nft: {
|
||||
contract: string
|
||||
token_id: string
|
||||
msg: Record<string, unknown>
|
||||
}
|
||||
}
|
||||
funds: Coin[]
|
||||
}
|
||||
|
||||
export interface ApproveMessage {
|
||||
sender: string
|
||||
contract: string
|
||||
msg: {
|
||||
approve: {
|
||||
spender: string
|
||||
token_id: string
|
||||
expires?: Expiration
|
||||
}
|
||||
}
|
||||
funds: Coin[]
|
||||
}
|
||||
|
||||
export interface RevokeMessage {
|
||||
sender: string
|
||||
contract: string
|
||||
|
||||
msg: {
|
||||
revoke: {
|
||||
spender: string
|
||||
token_id: string
|
||||
}
|
||||
}
|
||||
funds: Coin[]
|
||||
}
|
||||
|
||||
export interface ApproveAllMessage {
|
||||
sender: string
|
||||
contract: string
|
||||
msg: {
|
||||
approve_all: {
|
||||
operator: string
|
||||
expires?: Expiration
|
||||
}
|
||||
}
|
||||
funds: Coin[]
|
||||
}
|
||||
|
||||
export interface RevokeAllMessage {
|
||||
sender: string
|
||||
contract: string
|
||||
msg: {
|
||||
revoke_all: {
|
||||
operator: string
|
||||
}
|
||||
}
|
||||
funds: Coin[]
|
||||
}
|
||||
|
||||
export interface MintMessage {
|
||||
sender: string
|
||||
contract: string
|
||||
msg: {
|
||||
mint: {
|
||||
token_id: string
|
||||
owner: string
|
||||
token_uri?: string
|
||||
}
|
||||
}
|
||||
funds: Coin[]
|
||||
}
|
||||
|
||||
export interface BurnMessage {
|
||||
sender: string
|
||||
contract: string
|
||||
msg: {
|
||||
burn: {
|
||||
token_id: string
|
||||
}
|
||||
}
|
||||
funds: Coin[]
|
||||
}
|
||||
|
||||
export interface SG721Contract {
|
||||
@@ -114,121 +184,103 @@ export interface SG721Contract {
|
||||
codeId: number,
|
||||
initMsg: Record<string, unknown>,
|
||||
label: string,
|
||||
funds: Coin[],
|
||||
admin?: string
|
||||
admin?: string,
|
||||
) => Promise<InstantiateResponse>
|
||||
|
||||
use: (contractAddress: string) => SG721Instance
|
||||
|
||||
messages: (contractAddress: string) => Sg721Messages
|
||||
}
|
||||
|
||||
export const SG721 = (client: SigningCosmWasmClient): SG721Contract => {
|
||||
export const SG721 = (client: SigningCosmWasmClient, txSigner: string): SG721Contract => {
|
||||
const use = (contractAddress: string): SG721Instance => {
|
||||
const encode = (str: string): string =>
|
||||
Buffer.from(str, 'binary').toString('base64')
|
||||
const jsonToBinary = (json: Record<string, unknown>): string => {
|
||||
return toBase64(toUtf8(JSON.stringify(json)))
|
||||
}
|
||||
|
||||
const getOwnerOf = async (
|
||||
token_id: string,
|
||||
include_expired: boolean | null
|
||||
): Promise<any> => {
|
||||
const ownerOf = async (tokenId: string, includeExpired?: boolean | null): Promise<any> => {
|
||||
const res = await client.queryContractSmart(contractAddress, {
|
||||
owner_of: { token_id, include_expired },
|
||||
owner_of: { token_id: tokenId, include_expired: includeExpired },
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
||||
const getApproval = async (
|
||||
token_id: string,
|
||||
spender: string,
|
||||
include_expired: boolean | null
|
||||
): Promise<any> => {
|
||||
const approval = async (tokenId: string, spender: string, includeExpired?: boolean | null): Promise<any> => {
|
||||
const res = await client.queryContractSmart(contractAddress, {
|
||||
approval: { token_id, spender, include_expired },
|
||||
approval: { token_id: tokenId, spender, include_expired: includeExpired },
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
||||
const getApprovals = async (
|
||||
token_id: string,
|
||||
include_expired: boolean | null
|
||||
): Promise<any> => {
|
||||
const approvals = async (tokenId: string, includeExpired?: boolean | null): Promise<any> => {
|
||||
const res = await client.queryContractSmart(contractAddress, {
|
||||
approvals: { token_id, include_expired },
|
||||
approvals: { token_id: tokenId, include_expired: includeExpired },
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
||||
const getAllOperators = async (
|
||||
const allOperators = async (
|
||||
owner: string,
|
||||
include_expired: boolean | null,
|
||||
start_after: string | null,
|
||||
limit: number | null
|
||||
includeExpired?: boolean | null,
|
||||
startAfter?: string | null,
|
||||
limit?: number | null,
|
||||
): Promise<any> => {
|
||||
const res = await client.queryContractSmart(contractAddress, {
|
||||
all_operators: { owner, include_expired, start_after, limit },
|
||||
all_operators: { owner, include_expired: includeExpired, start_after: startAfter, limit },
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
||||
const getNumTokens = async (): Promise<any> => {
|
||||
const numTokens = async (): Promise<any> => {
|
||||
const res = await client.queryContractSmart(contractAddress, {
|
||||
num_tokens: {},
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
||||
const getContractInfo = async (): Promise<any> => {
|
||||
const contractInfo = async (): Promise<any> => {
|
||||
const res = await client.queryContractSmart(contractAddress, {
|
||||
contract_info: {},
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
||||
const getNftInfo = async (token_id: string): Promise<any> => {
|
||||
const nftInfo = async (tokenId: string): Promise<any> => {
|
||||
const res = await client.queryContractSmart(contractAddress, {
|
||||
nft_info: { token_id },
|
||||
nft_info: { token_id: tokenId },
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
||||
const getAllNftInfo = async (
|
||||
token_id: string,
|
||||
include_expired: boolean | null
|
||||
): Promise<any> => {
|
||||
const allNftInfo = async (tokenId: string, includeExpired?: boolean | null): Promise<any> => {
|
||||
const res = await client.queryContractSmart(contractAddress, {
|
||||
all_nft_info: { token_id, include_expired },
|
||||
all_nft_info: { token_id: tokenId, include_expired: includeExpired },
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
||||
const getTokens = async (
|
||||
owner: string,
|
||||
start_after: string | null,
|
||||
limit: number | null
|
||||
): Promise<any> => {
|
||||
const tokens = async (owner: string, startAfter?: string | null, limit?: number | null): Promise<any> => {
|
||||
const res = await client.queryContractSmart(contractAddress, {
|
||||
tokens: { owner, start_after, limit },
|
||||
tokens: { owner, start_after: startAfter, limit },
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
||||
const getAllTokens = async (
|
||||
start_after: string | null,
|
||||
limit: number | null
|
||||
): Promise<any> => {
|
||||
const allTokens = async (startAfter?: string | null, limit?: number | null): Promise<any> => {
|
||||
const res = await client.queryContractSmart(contractAddress, {
|
||||
all_tokens: { start_after, limit },
|
||||
all_tokens: { start_after: startAfter, limit },
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
||||
const getMinter = async (): Promise<any> => {
|
||||
const minter = async (): Promise<any> => {
|
||||
const res = await client.queryContractSmart(contractAddress, {
|
||||
minter: {},
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
||||
const getCollectionInfo = async (): Promise<any> => {
|
||||
const collectionInfo = async (): Promise<any> => {
|
||||
const res = await client.queryContractSmart(contractAddress, {
|
||||
collection_info: {},
|
||||
})
|
||||
@@ -236,144 +288,121 @@ export const SG721 = (client: SigningCosmWasmClient): SG721Contract => {
|
||||
}
|
||||
|
||||
//Execute
|
||||
const transferNft = async (
|
||||
senderAddress: string,
|
||||
recipient: string,
|
||||
token_id: string
|
||||
): Promise<string> => {
|
||||
const transferNft = async (recipient: string, tokenId: string): Promise<string> => {
|
||||
const res = await client.execute(
|
||||
senderAddress,
|
||||
txSigner,
|
||||
contractAddress,
|
||||
{
|
||||
transfer_nft: { recipient, token_id },
|
||||
transfer_nft: { recipient, token_id: tokenId },
|
||||
},
|
||||
'auto',
|
||||
''
|
||||
'',
|
||||
)
|
||||
|
||||
return res.transactionHash
|
||||
}
|
||||
|
||||
const sendNft = async (
|
||||
senderAddress: string,
|
||||
contract: string,
|
||||
token_id: string,
|
||||
msg: string //Binary
|
||||
tokenId: string,
|
||||
msg: Record<string, unknown>, //Binary
|
||||
): Promise<string> => {
|
||||
const res = await client.execute(
|
||||
senderAddress,
|
||||
txSigner,
|
||||
contractAddress,
|
||||
{
|
||||
send_nft: { contract, token_id, msg: encode(msg) },
|
||||
send_nft: { contract, token_id: tokenId, msg: jsonToBinary(msg) },
|
||||
},
|
||||
'auto',
|
||||
''
|
||||
'',
|
||||
)
|
||||
|
||||
return res.transactionHash
|
||||
}
|
||||
|
||||
const approve = async (
|
||||
senderAddress: string,
|
||||
spender: string,
|
||||
token_id: string,
|
||||
expires: Expiration | null
|
||||
): Promise<string> => {
|
||||
const approve = async (spender: string, tokenId: string, expires?: Expiration): Promise<string> => {
|
||||
const res = await client.execute(
|
||||
senderAddress,
|
||||
txSigner,
|
||||
contractAddress,
|
||||
{
|
||||
approve: { spender, token_id, expires },
|
||||
approve: { spender, token_id: tokenId, expires },
|
||||
},
|
||||
'auto',
|
||||
''
|
||||
'',
|
||||
)
|
||||
|
||||
return res.transactionHash
|
||||
}
|
||||
|
||||
const revoke = async (
|
||||
senderAddress: string,
|
||||
spender: string,
|
||||
token_id: string
|
||||
): Promise<string> => {
|
||||
const revoke = async (spender: string, tokenId: string): Promise<string> => {
|
||||
const res = await client.execute(
|
||||
senderAddress,
|
||||
txSigner,
|
||||
contractAddress,
|
||||
{
|
||||
revoke: { spender, token_id },
|
||||
revoke: { spender, token_id: tokenId },
|
||||
},
|
||||
'auto',
|
||||
''
|
||||
'',
|
||||
)
|
||||
|
||||
return res.transactionHash
|
||||
}
|
||||
|
||||
const approveAll = async (
|
||||
senderAddress: string,
|
||||
operator: string,
|
||||
expires: Expiration | null
|
||||
): Promise<string> => {
|
||||
const approveAll = async (operator: string, expires?: Expiration): Promise<string> => {
|
||||
const res = await client.execute(
|
||||
senderAddress,
|
||||
txSigner,
|
||||
contractAddress,
|
||||
{
|
||||
approve_all: { operator, expires },
|
||||
},
|
||||
'auto',
|
||||
''
|
||||
'',
|
||||
)
|
||||
|
||||
return res.transactionHash
|
||||
}
|
||||
|
||||
const revokeAll = async (
|
||||
senderAddress: string,
|
||||
operator: string
|
||||
): Promise<string> => {
|
||||
const revokeAll = async (operator: string): Promise<string> => {
|
||||
const res = await client.execute(
|
||||
senderAddress,
|
||||
txSigner,
|
||||
contractAddress,
|
||||
{
|
||||
revoke_all: { operator },
|
||||
},
|
||||
'auto',
|
||||
''
|
||||
'',
|
||||
)
|
||||
|
||||
return res.transactionHash
|
||||
}
|
||||
|
||||
const mint = async (
|
||||
senderAddress: string,
|
||||
msg: string
|
||||
): Promise<string> => {
|
||||
const mint = async (tokenId: string, owner: string, tokenURI?: string): Promise<string> => {
|
||||
const res = await client.execute(
|
||||
senderAddress,
|
||||
txSigner,
|
||||
contractAddress,
|
||||
{
|
||||
mint: { msg },
|
||||
mint: {
|
||||
token_id: tokenId,
|
||||
owner,
|
||||
token_uri: tokenURI,
|
||||
},
|
||||
},
|
||||
'auto',
|
||||
''
|
||||
'',
|
||||
)
|
||||
|
||||
return res.transactionHash
|
||||
}
|
||||
|
||||
const burn = async (
|
||||
senderAddress: string,
|
||||
token_id: string
|
||||
): Promise<string> => {
|
||||
const burn = async (tokenId: string): Promise<string> => {
|
||||
const res = await client.execute(
|
||||
senderAddress,
|
||||
txSigner,
|
||||
contractAddress,
|
||||
{
|
||||
burn: { token_id },
|
||||
burn: { token_id: tokenId },
|
||||
},
|
||||
'auto',
|
||||
''
|
||||
'',
|
||||
)
|
||||
|
||||
return res.transactionHash
|
||||
@@ -381,18 +410,18 @@ export const SG721 = (client: SigningCosmWasmClient): SG721Contract => {
|
||||
|
||||
return {
|
||||
contractAddress,
|
||||
getOwnerOf,
|
||||
getApproval,
|
||||
getApprovals,
|
||||
getAllOperators,
|
||||
getNumTokens,
|
||||
getContractInfo,
|
||||
getNftInfo,
|
||||
getAllNftInfo,
|
||||
getTokens,
|
||||
getAllTokens,
|
||||
getMinter,
|
||||
getCollectionInfo,
|
||||
ownerOf,
|
||||
approval,
|
||||
approvals,
|
||||
allOperators,
|
||||
numTokens,
|
||||
contractInfo,
|
||||
nftInfo,
|
||||
allNftInfo,
|
||||
tokens,
|
||||
allTokens,
|
||||
minter,
|
||||
collectionInfo,
|
||||
transferNft,
|
||||
sendNft,
|
||||
approve,
|
||||
@@ -409,26 +438,144 @@ export const SG721 = (client: SigningCosmWasmClient): SG721Contract => {
|
||||
codeId: number,
|
||||
initMsg: Record<string, unknown>,
|
||||
label: string,
|
||||
funds: Coin[],
|
||||
admin?: string
|
||||
admin?: string,
|
||||
): Promise<InstantiateResponse> => {
|
||||
const result = await client.instantiate(
|
||||
senderAddress,
|
||||
codeId,
|
||||
initMsg,
|
||||
label,
|
||||
'auto',
|
||||
{
|
||||
funds,
|
||||
memo: '',
|
||||
admin,
|
||||
}
|
||||
)
|
||||
const result = await client.instantiate(senderAddress, codeId, initMsg, label, 'auto', {
|
||||
funds: [coin('1000000000', 'ustars')],
|
||||
memo: '',
|
||||
admin,
|
||||
})
|
||||
return {
|
||||
contractAddress: result.contractAddress,
|
||||
transactionHash: result.transactionHash,
|
||||
}
|
||||
}
|
||||
|
||||
return { use, instantiate }
|
||||
const messages = (contractAddress: string) => {
|
||||
const transferNft = (recipient: string, tokenId: string) => {
|
||||
return {
|
||||
sender: txSigner,
|
||||
contract: contractAddress,
|
||||
msg: {
|
||||
transfer_nft: {
|
||||
recipient,
|
||||
token_id: tokenId,
|
||||
},
|
||||
},
|
||||
funds: [],
|
||||
}
|
||||
}
|
||||
|
||||
const sendNft = (contract: string, tokenId: string, msg: Record<string, unknown>) => {
|
||||
return {
|
||||
sender: txSigner,
|
||||
contract: contractAddress,
|
||||
msg: {
|
||||
send_nft: {
|
||||
contract,
|
||||
token_id: tokenId,
|
||||
msg,
|
||||
},
|
||||
},
|
||||
funds: [],
|
||||
}
|
||||
}
|
||||
|
||||
const approve = (spender: string, tokenId: string, expires?: Expiration) => {
|
||||
return {
|
||||
sender: txSigner,
|
||||
contract: contractAddress,
|
||||
msg: {
|
||||
approve: {
|
||||
spender,
|
||||
token_id: tokenId,
|
||||
expires,
|
||||
},
|
||||
},
|
||||
funds: [],
|
||||
}
|
||||
}
|
||||
|
||||
const revoke = (spender: string, tokenId: string) => {
|
||||
return {
|
||||
sender: txSigner,
|
||||
contract: contractAddress,
|
||||
msg: {
|
||||
revoke: {
|
||||
spender,
|
||||
token_id: tokenId,
|
||||
},
|
||||
},
|
||||
funds: [],
|
||||
}
|
||||
}
|
||||
|
||||
const approveAll = (operator: string, expires?: Expiration) => {
|
||||
return {
|
||||
sender: txSigner,
|
||||
contract: contractAddress,
|
||||
msg: {
|
||||
approve_all: {
|
||||
operator,
|
||||
expires,
|
||||
},
|
||||
},
|
||||
funds: [],
|
||||
}
|
||||
}
|
||||
|
||||
const revokeAll = (operator: string) => {
|
||||
return {
|
||||
sender: txSigner,
|
||||
contract: contractAddress,
|
||||
msg: {
|
||||
revoke_all: {
|
||||
operator,
|
||||
},
|
||||
},
|
||||
funds: [],
|
||||
}
|
||||
}
|
||||
|
||||
const mint = (tokenId: string, owner: string, tokenURI?: string) => {
|
||||
return {
|
||||
sender: txSigner,
|
||||
contract: contractAddress,
|
||||
msg: {
|
||||
mint: {
|
||||
token_id: tokenId,
|
||||
owner,
|
||||
token_uri: tokenURI,
|
||||
},
|
||||
},
|
||||
funds: [],
|
||||
}
|
||||
}
|
||||
|
||||
const burn = (tokenId: string) => {
|
||||
return {
|
||||
sender: txSigner,
|
||||
contract: contractAddress,
|
||||
msg: {
|
||||
burn: {
|
||||
token_id: tokenId,
|
||||
},
|
||||
},
|
||||
funds: [],
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
transferNft,
|
||||
sendNft,
|
||||
approve,
|
||||
revoke,
|
||||
approveAll,
|
||||
revokeAll,
|
||||
mint,
|
||||
burn,
|
||||
}
|
||||
}
|
||||
|
||||
return { use, instantiate, messages }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
import type { Expiration, SG721Instance } from '../index'
|
||||
import { useSG721Contract } from '../index'
|
||||
|
||||
export type ExecuteType = typeof EXECUTE_TYPES[number]
|
||||
|
||||
export const EXECUTE_TYPES = [
|
||||
'transfer_nft',
|
||||
'send_nft',
|
||||
'approve',
|
||||
'revoke',
|
||||
'approve_all',
|
||||
'revoke_all',
|
||||
'mint',
|
||||
'burn',
|
||||
] as const
|
||||
|
||||
export interface ExecuteListItem {
|
||||
id: ExecuteType
|
||||
name: string
|
||||
description?: string
|
||||
}
|
||||
|
||||
export const EXECUTE_LIST: ExecuteListItem[] = [
|
||||
{
|
||||
id: 'transfer_nft',
|
||||
name: 'Transfer NFT',
|
||||
description: `Transfer a token to an address`,
|
||||
},
|
||||
{
|
||||
id: 'send_nft',
|
||||
name: 'Send NFT',
|
||||
description: `Send a token to a contract and execute a message afterwards`,
|
||||
},
|
||||
{
|
||||
id: 'approve',
|
||||
name: 'Approve',
|
||||
description: `Allow an operator to transfer/send a given token from the owner's account`,
|
||||
},
|
||||
{
|
||||
id: 'revoke',
|
||||
name: 'Revoke',
|
||||
description: `Remove permissions of an operator from the owner's account`,
|
||||
},
|
||||
{
|
||||
id: 'approve_all',
|
||||
name: 'Approve All',
|
||||
description: `Allow an operator to transfer/send all tokens from owner's account`,
|
||||
},
|
||||
{
|
||||
id: 'revoke_all',
|
||||
name: 'Revoke All',
|
||||
description: `Remove permissions of an operator from the owner's account`,
|
||||
},
|
||||
{
|
||||
id: 'mint',
|
||||
name: 'Mint',
|
||||
description: `Mint a new token to owner's account`,
|
||||
},
|
||||
{
|
||||
id: 'burn',
|
||||
name: 'Burn',
|
||||
description: `Burn a token transaction sender has access to`,
|
||||
},
|
||||
]
|
||||
|
||||
export interface DispatchExecuteProps {
|
||||
type: ExecuteType
|
||||
[k: string]: unknown
|
||||
}
|
||||
|
||||
type Select<T extends ExecuteType> = T
|
||||
|
||||
/** @see {@link SG721Instance} */
|
||||
export type DispatchExecuteArgs = {
|
||||
contract: string
|
||||
messages?: SG721Instance
|
||||
} & (
|
||||
| { type: undefined }
|
||||
| { type: Select<'transfer_nft'>; recipient: string; tokenId: string }
|
||||
| { type: Select<'send_nft'>; recipient: string; tokenId: string; msg: Record<string, unknown> }
|
||||
| { type: Select<'approve'>; recipient: string; tokenId: string; expiration?: Expiration }
|
||||
| { type: Select<'revoke'>; recipient: string; tokenId: string }
|
||||
| { type: Select<'approve_all'>; operator: string; expiration?: Expiration }
|
||||
| { type: Select<'revoke_all'>; operator: string }
|
||||
| { type: Select<'mint'>; recipient: string; tokenId: string; tokenURI?: string }
|
||||
| { type: Select<'burn'>; tokenId: string }
|
||||
)
|
||||
|
||||
export const dispatchExecute = async (args: DispatchExecuteArgs) => {
|
||||
const { messages } = args
|
||||
if (!messages) {
|
||||
throw new Error('cannot dispatch execute, messages is not defined')
|
||||
}
|
||||
switch (args.type) {
|
||||
case 'transfer_nft': {
|
||||
return messages.transferNft(args.recipient, args.tokenId)
|
||||
}
|
||||
case 'send_nft': {
|
||||
return messages.sendNft(args.recipient, args.tokenId, args.msg)
|
||||
}
|
||||
case 'approve': {
|
||||
return messages.approve(args.recipient, args.tokenId, args.expiration)
|
||||
}
|
||||
case 'revoke': {
|
||||
return messages.revoke(args.recipient, args.tokenId)
|
||||
}
|
||||
case 'approve_all': {
|
||||
return messages.approveAll(args.operator, args.expiration)
|
||||
}
|
||||
case 'revoke_all': {
|
||||
return messages.revokeAll(args.operator)
|
||||
}
|
||||
case 'mint': {
|
||||
return messages.mint(args.recipient, args.tokenId, args.tokenURI)
|
||||
}
|
||||
case 'burn': {
|
||||
return messages.burn(args.tokenId)
|
||||
}
|
||||
default: {
|
||||
throw new Error('unknown execute type')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const previewExecutePayload = (args: DispatchExecuteArgs) => {
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
const { messages } = useSG721Contract()
|
||||
const { contract } = args
|
||||
switch (args.type) {
|
||||
case 'transfer_nft': {
|
||||
return messages(contract)?.transferNft(args.recipient, args.tokenId)
|
||||
}
|
||||
case 'send_nft': {
|
||||
return messages(contract)?.sendNft(args.recipient, args.tokenId, args.msg)
|
||||
}
|
||||
case 'approve': {
|
||||
return messages(contract)?.approve(args.recipient, args.tokenId, args.expiration)
|
||||
}
|
||||
case 'revoke': {
|
||||
return messages(contract)?.revoke(args.recipient, args.tokenId)
|
||||
}
|
||||
case 'approve_all': {
|
||||
return messages(contract)?.approveAll(args.operator, args.expiration)
|
||||
}
|
||||
case 'revoke_all': {
|
||||
return messages(contract)?.revokeAll(args.operator)
|
||||
}
|
||||
case 'mint': {
|
||||
return messages(contract)?.mint(args.recipient, args.tokenId, args.tokenURI)
|
||||
}
|
||||
case 'burn': {
|
||||
return messages(contract)?.burn(args.tokenId)
|
||||
}
|
||||
default: {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const isEitherType = <T extends ExecuteType>(type: unknown, arr: T[]): type is T => {
|
||||
return arr.some((val) => type === val)
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
import type { SG721Instance } from '../contract'
|
||||
|
||||
export type QueryType = typeof QUERY_TYPES[number]
|
||||
|
||||
export const QUERY_TYPES = [
|
||||
'owner_of',
|
||||
'approval',
|
||||
'approvals',
|
||||
'all_operators',
|
||||
'num_tokens',
|
||||
'contract_info',
|
||||
'nft_info',
|
||||
'all_nft_info',
|
||||
'tokens',
|
||||
'all_tokens',
|
||||
'minter',
|
||||
'collection_info',
|
||||
] as const
|
||||
|
||||
export interface QueryListItem {
|
||||
id: QueryType
|
||||
name: string
|
||||
description?: string
|
||||
}
|
||||
|
||||
export const QUERY_LIST: QueryListItem[] = [
|
||||
{ id: 'owner_of', name: 'Owner Of', description: 'View current owner of given token' },
|
||||
{ id: 'approval', name: 'Approval', description: 'View address that has access to given token' },
|
||||
{ id: 'approvals', name: 'Approvals', description: 'View all approvals of a given token' },
|
||||
{
|
||||
id: 'all_operators',
|
||||
name: 'All Operators',
|
||||
description: "List all the operators that has access all of the owner's tokens",
|
||||
},
|
||||
{ id: 'num_tokens', name: 'Number of Tokens', description: 'View total number of tokens minted' },
|
||||
{ id: 'contract_info', name: 'Contract Info', description: 'View top-level metadata of contract' },
|
||||
{ id: 'nft_info', name: 'NFT Info', description: 'View metadata of a given token' },
|
||||
{ id: 'all_nft_info', name: 'All NFT Info', description: 'View metadata and owner info of a given token' },
|
||||
{ id: 'tokens', name: 'Tokens', description: 'View all the tokens owned by given address' },
|
||||
{ id: 'all_tokens', name: 'All Tokens', description: 'List all the tokens controlled by the contract' },
|
||||
{ id: 'minter', name: 'Minter', description: 'View current minter of the contract' },
|
||||
{ id: 'collection_info', name: 'Collection Info', description: 'View metadata of a given collection' },
|
||||
]
|
||||
|
||||
export interface DispatchQueryProps {
|
||||
messages: SG721Instance | undefined
|
||||
type: QueryType
|
||||
tokenId: string
|
||||
address: string
|
||||
}
|
||||
|
||||
export const dispatchQuery = (props: DispatchQueryProps) => {
|
||||
const { tokenId, messages, type, address } = props
|
||||
switch (type) {
|
||||
case 'owner_of': {
|
||||
return messages?.ownerOf(tokenId)
|
||||
}
|
||||
case 'approval': {
|
||||
return messages?.approval(tokenId, address)
|
||||
}
|
||||
case 'approvals': {
|
||||
return messages?.approvals(tokenId)
|
||||
}
|
||||
case 'all_operators': {
|
||||
return messages?.allOperators(address)
|
||||
}
|
||||
case 'num_tokens': {
|
||||
return messages?.numTokens()
|
||||
}
|
||||
case 'contract_info': {
|
||||
return messages?.contractInfo()
|
||||
}
|
||||
case 'nft_info': {
|
||||
return messages?.nftInfo(tokenId)
|
||||
}
|
||||
case 'all_nft_info': {
|
||||
return messages?.allNftInfo(tokenId, null)
|
||||
}
|
||||
case 'tokens': {
|
||||
return messages?.tokens(address)
|
||||
}
|
||||
case 'all_tokens': {
|
||||
return messages?.allTokens()
|
||||
}
|
||||
case 'minter': {
|
||||
return messages?.minter()
|
||||
}
|
||||
case 'collection_info': {
|
||||
return messages?.collectionInfo()
|
||||
}
|
||||
default: {
|
||||
throw new Error('unknown query type')
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
import type { Coin } from '@cosmjs/proto-signing'
|
||||
import { useWallet } from 'contexts/wallet'
|
||||
import { Coin } from 'cosmwasm'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
|
||||
import { SG721 as initContract, SG721Contract, SG721Instance } from './contract'
|
||||
import type { SG721Contract, SG721Instance, Sg721Messages } from './contract'
|
||||
import { SG721 as initContract } from './contract'
|
||||
|
||||
interface InstantiateResponse {
|
||||
readonly contractAddress: string
|
||||
@@ -14,11 +15,12 @@ export interface UseSG721ContractProps {
|
||||
codeId: number,
|
||||
initMsg: Record<string, unknown>,
|
||||
label: string,
|
||||
funds: Coin[],
|
||||
admin?: string
|
||||
admin?: string,
|
||||
funds?: Coin[],
|
||||
) => Promise<InstantiateResponse>
|
||||
use: (customAddress: string) => SG721Instance | undefined
|
||||
updateContractAddress: (contractAddress: string) => void
|
||||
messages: (contractAddress: string) => Sg721Messages | undefined
|
||||
}
|
||||
|
||||
export function useSG721Contract(): UseSG721ContractProps {
|
||||
@@ -33,12 +35,8 @@ export function useSG721Contract(): UseSG721ContractProps {
|
||||
|
||||
useEffect(() => {
|
||||
if (wallet.initialized) {
|
||||
const getSG721Instance = async (): Promise<void> => {
|
||||
const SG721Contract = initContract(wallet.getClient())
|
||||
setSG721(SG721Contract)
|
||||
}
|
||||
|
||||
getSG721Instance()
|
||||
const contract = initContract(wallet.getClient(), wallet.address)
|
||||
setSG721(contract)
|
||||
}
|
||||
}, [wallet])
|
||||
|
||||
@@ -47,27 +45,33 @@ export function useSG721Contract(): UseSG721ContractProps {
|
||||
}
|
||||
|
||||
const instantiate = useCallback(
|
||||
(codeId, initMsg, label, admin?): Promise<InstantiateResponse> => {
|
||||
(codeId: number, initMsg: Record<string, unknown>, label: string, admin?: string): Promise<InstantiateResponse> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!SG721) return reject('Contract is not initialized.')
|
||||
SG721.instantiate(wallet.address, codeId, initMsg, label, admin)
|
||||
.then(resolve)
|
||||
.catch(reject)
|
||||
if (!SG721) {
|
||||
reject(new Error('Contract is not initialized.'))
|
||||
return
|
||||
}
|
||||
SG721.instantiate(wallet.address, codeId, initMsg, label, admin).then(resolve).catch(reject)
|
||||
})
|
||||
},
|
||||
[SG721, wallet]
|
||||
[SG721, wallet],
|
||||
)
|
||||
|
||||
const use = useCallback(
|
||||
(customAddress = ''): SG721Instance | undefined => {
|
||||
return SG721?.use(address || customAddress)
|
||||
},
|
||||
[SG721, address]
|
||||
[SG721, address],
|
||||
)
|
||||
|
||||
const messages = useCallback((): Sg721Messages | undefined => {
|
||||
return SG721?.messages(address)
|
||||
}, [SG721, address])
|
||||
|
||||
return {
|
||||
instantiate,
|
||||
use,
|
||||
updateContractAddress,
|
||||
messages,
|
||||
}
|
||||
}
|
||||
|
||||
+179
-70
@@ -1,7 +1,6 @@
|
||||
import { SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate'
|
||||
import { Coin } from '@cosmjs/proto-signing'
|
||||
|
||||
type Expiration = { at_height: number } | { at_time: string } | { never: {} }
|
||||
import type { SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate'
|
||||
import type { Coin } from '@cosmjs/proto-signing'
|
||||
import { coin } from '@cosmjs/proto-signing'
|
||||
|
||||
export interface InstantiateResponse {
|
||||
readonly contractAddress: string
|
||||
@@ -23,39 +22,98 @@ export interface WhiteListInstance {
|
||||
hasStarted: () => Promise<boolean>
|
||||
hasEnded: () => Promise<boolean>
|
||||
isActive: () => Promise<boolean>
|
||||
members: (limit: number, startAfter?: string) => Promise<string[]>
|
||||
members: (startAfter?: string, limit?: number) => Promise<string[]>
|
||||
hasMember: (member: string) => Promise<boolean>
|
||||
config: () => Promise<ConfigResponse>
|
||||
|
||||
//Execute
|
||||
updateStartTime: (startTime: string) => Promise<string>
|
||||
updateEndTime: (endTime: string) => Promise<string>
|
||||
addMembers: (to_add: string[]) => Promise<string>
|
||||
removeMembers: (to_remove: string[]) => Promise<string>
|
||||
addMembers: (memberList: string[]) => Promise<string>
|
||||
removeMembers: (memberList: string[]) => Promise<string>
|
||||
updatePerAddressLimit: (limit: number) => Promise<string>
|
||||
increaseMemberLimit: (limit: number) => Promise<string>
|
||||
}
|
||||
|
||||
export interface WhitelistMessages {
|
||||
updateStartTime: (startTime: string) => UpdateStartTimeMessage
|
||||
updateEndTime: (endTime: string) => UpdateEndTimeMessage
|
||||
addMembers: (memberList: string[]) => AddMembersMessage
|
||||
removeMembers: (memberList: string[]) => RemoveMembersMessage
|
||||
updatePerAddressLimit: (limit: number) => UpdatePerAddressLimitMessage
|
||||
increaseMemberLimit: (limit: number) => IncreaseMemberLimitMessage
|
||||
}
|
||||
|
||||
export interface UpdateStartTimeMessage {
|
||||
sender: string
|
||||
contract: string
|
||||
msg: {
|
||||
update_start_time: string
|
||||
}
|
||||
funds: Coin[]
|
||||
}
|
||||
|
||||
export interface UpdateEndTimeMessage {
|
||||
sender: string
|
||||
contract: string
|
||||
msg: {
|
||||
update_end_time: string
|
||||
}
|
||||
funds: Coin[]
|
||||
}
|
||||
|
||||
export interface AddMembersMessage {
|
||||
sender: string
|
||||
contract: string
|
||||
msg: {
|
||||
add_members: { to_add: string[] }
|
||||
}
|
||||
funds: Coin[]
|
||||
}
|
||||
|
||||
export interface RemoveMembersMessage {
|
||||
sender: string
|
||||
contract: string
|
||||
msg: {
|
||||
remove_members: { to_remove: string[] }
|
||||
}
|
||||
funds: Coin[]
|
||||
}
|
||||
|
||||
export interface UpdatePerAddressLimitMessage {
|
||||
sender: string
|
||||
|
||||
contract: string
|
||||
msg: {
|
||||
update_per_address_limit: number
|
||||
}
|
||||
funds: Coin[]
|
||||
}
|
||||
|
||||
export interface IncreaseMemberLimitMessage {
|
||||
sender: string
|
||||
contract: string
|
||||
msg: {
|
||||
increase_member_limit: number
|
||||
}
|
||||
funds: Coin[]
|
||||
}
|
||||
|
||||
export interface WhiteListContract {
|
||||
instantiate: (
|
||||
senderAddress: string,
|
||||
codeId: number,
|
||||
initMsg: Record<string, unknown>,
|
||||
label: string,
|
||||
admin?: string,
|
||||
funds?: Coin[]
|
||||
) => Promise<InstantiateResponse>
|
||||
|
||||
use: (contractAddress: string) => WhiteListInstance
|
||||
|
||||
messages: (contractAddress: string) => WhitelistMessages
|
||||
}
|
||||
|
||||
export const WhiteList = (
|
||||
client: SigningCosmWasmClient,
|
||||
senderAddress: string
|
||||
): WhiteListContract => {
|
||||
export const WhiteList = (client: SigningCosmWasmClient, txSigner: string): WhiteListContract => {
|
||||
const use = (contractAddress: string): WhiteListInstance => {
|
||||
console.log(client, 'client')
|
||||
console.log(senderAddress, 'senderAddress')
|
||||
///QUERY START
|
||||
const hasStarted = async (): Promise<boolean> => {
|
||||
return client.queryContractSmart(contractAddress, { has_started: {} })
|
||||
@@ -69,10 +127,7 @@ export const WhiteList = (
|
||||
return client.queryContractSmart(contractAddress, { is_active: {} })
|
||||
}
|
||||
|
||||
const members = async (
|
||||
limit: number,
|
||||
startAfter?: string
|
||||
): Promise<string[]> => {
|
||||
const members = async (startAfter?: string, limit?: number): Promise<string[]> => {
|
||||
return client.queryContractSmart(contractAddress, {
|
||||
members: { limit, start_after: startAfter },
|
||||
})
|
||||
@@ -92,63 +147,50 @@ export const WhiteList = (
|
||||
/// QUERY END
|
||||
/// EXECUTE START
|
||||
const updateStartTime = async (startTime: string): Promise<string> => {
|
||||
const res = await client.execute(
|
||||
senderAddress,
|
||||
contractAddress,
|
||||
{ update_start_time: startTime },
|
||||
'auto',
|
||||
'memo'
|
||||
)
|
||||
const res = await client.execute(txSigner, contractAddress, { update_start_time: startTime }, 'auto')
|
||||
return res.transactionHash
|
||||
}
|
||||
|
||||
const updateEndTime = async (endTime: string): Promise<string> => {
|
||||
const res = await client.execute(txSigner, contractAddress, { update_end_time: endTime }, 'auto')
|
||||
return res.transactionHash
|
||||
}
|
||||
|
||||
const addMembers = async (memberList: string[]): Promise<string> => {
|
||||
const res = await client.execute(
|
||||
senderAddress,
|
||||
txSigner,
|
||||
contractAddress,
|
||||
{ update_end_time: endTime },
|
||||
'auto'
|
||||
{
|
||||
add_members: {
|
||||
to_add: memberList,
|
||||
},
|
||||
},
|
||||
'auto',
|
||||
)
|
||||
return res.transactionHash
|
||||
}
|
||||
|
||||
const addMembers = async (to_add: string[]): Promise<string> => {
|
||||
const removeMembers = async (memberList: string[]): Promise<string> => {
|
||||
const res = await client.execute(
|
||||
senderAddress,
|
||||
txSigner,
|
||||
contractAddress,
|
||||
{ add_members: to_add },
|
||||
'auto'
|
||||
)
|
||||
return res.transactionHash
|
||||
}
|
||||
|
||||
const removeMembers = async (to_remove: string[]): Promise<string> => {
|
||||
const res = await client.execute(
|
||||
senderAddress,
|
||||
contractAddress,
|
||||
{ remove_members: to_remove },
|
||||
'auto'
|
||||
{
|
||||
remove_members: {
|
||||
to_remove: memberList,
|
||||
},
|
||||
},
|
||||
'auto',
|
||||
)
|
||||
return res.transactionHash
|
||||
}
|
||||
|
||||
const updatePerAddressLimit = async (limit: number): Promise<string> => {
|
||||
const res = await client.execute(
|
||||
senderAddress,
|
||||
contractAddress,
|
||||
{ update_per_address_limit: limit },
|
||||
'auto'
|
||||
)
|
||||
const res = await client.execute(txSigner, contractAddress, { update_per_address_limit: limit }, 'auto')
|
||||
return res.transactionHash
|
||||
}
|
||||
|
||||
const increaseMemberLimit = async (limit: number): Promise<string> => {
|
||||
const res = await client.execute(
|
||||
senderAddress,
|
||||
contractAddress,
|
||||
{ increase_member_limit: limit },
|
||||
'auto'
|
||||
)
|
||||
const res = await client.execute(txSigner, contractAddress, { increase_member_limit: limit }, 'auto')
|
||||
return res.transactionHash
|
||||
}
|
||||
/// EXECUTE END
|
||||
@@ -171,25 +213,15 @@ export const WhiteList = (
|
||||
}
|
||||
|
||||
const instantiate = async (
|
||||
senderAddress: string,
|
||||
codeId: number,
|
||||
initMsg: Record<string, unknown>,
|
||||
label: string,
|
||||
admin?: string,
|
||||
funds?: Coin[]
|
||||
): Promise<InstantiateResponse> => {
|
||||
console.log('Funds:' + funds)
|
||||
const result = await client.instantiate(
|
||||
senderAddress,
|
||||
codeId,
|
||||
initMsg,
|
||||
label,
|
||||
'auto',
|
||||
{
|
||||
funds,
|
||||
admin,
|
||||
}
|
||||
)
|
||||
const result = await client.instantiate(txSigner, codeId, initMsg, label, 'auto', {
|
||||
funds: [coin('100000000', 'ustars')],
|
||||
admin,
|
||||
})
|
||||
|
||||
return {
|
||||
contractAddress: result.contractAddress,
|
||||
@@ -197,5 +229,82 @@ export const WhiteList = (
|
||||
}
|
||||
}
|
||||
|
||||
return { use, instantiate }
|
||||
const messages = (contractAddress: string) => {
|
||||
const updateStartTime = (startTime: string) => {
|
||||
return {
|
||||
sender: txSigner,
|
||||
contract: contractAddress,
|
||||
msg: {
|
||||
update_start_time: startTime,
|
||||
},
|
||||
funds: [],
|
||||
}
|
||||
}
|
||||
|
||||
const updateEndTime = (endTime: string) => {
|
||||
return {
|
||||
sender: txSigner,
|
||||
contract: contractAddress,
|
||||
msg: {
|
||||
update_end_time: endTime,
|
||||
},
|
||||
funds: [],
|
||||
}
|
||||
}
|
||||
|
||||
const addMembers = (memberList: string[]) => {
|
||||
return {
|
||||
sender: txSigner,
|
||||
contract: contractAddress,
|
||||
msg: {
|
||||
add_members: { to_add: memberList },
|
||||
},
|
||||
funds: [],
|
||||
}
|
||||
}
|
||||
|
||||
const removeMembers = (memberList: string[]) => {
|
||||
return {
|
||||
sender: txSigner,
|
||||
contract: contractAddress,
|
||||
msg: {
|
||||
remove_members: { to_remove: memberList },
|
||||
},
|
||||
funds: [],
|
||||
}
|
||||
}
|
||||
|
||||
const updatePerAddressLimit = (limit: number) => {
|
||||
return {
|
||||
sender: txSigner,
|
||||
contract: contractAddress,
|
||||
msg: {
|
||||
update_per_address_limit: limit,
|
||||
},
|
||||
funds: [],
|
||||
}
|
||||
}
|
||||
|
||||
const increaseMemberLimit = (limit: number) => {
|
||||
return {
|
||||
sender: txSigner,
|
||||
contract: contractAddress,
|
||||
msg: {
|
||||
increase_member_limit: limit,
|
||||
},
|
||||
funds: [],
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
updateStartTime,
|
||||
updateEndTime,
|
||||
addMembers,
|
||||
removeMembers,
|
||||
updatePerAddressLimit,
|
||||
increaseMemberLimit,
|
||||
}
|
||||
}
|
||||
|
||||
return { use, instantiate, messages }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
import type { WhiteListInstance } from '../index'
|
||||
import { useWhiteListContract } from '../index'
|
||||
|
||||
export type ExecuteType = typeof EXECUTE_TYPES[number]
|
||||
|
||||
export const EXECUTE_TYPES = [
|
||||
'update_start_time',
|
||||
'update_end_time',
|
||||
'add_members',
|
||||
'remove_members',
|
||||
'update_per_address_limit',
|
||||
'increase_member_limit',
|
||||
] as const
|
||||
|
||||
export interface ExecuteListItem {
|
||||
id: ExecuteType
|
||||
name: string
|
||||
description?: string
|
||||
}
|
||||
|
||||
export const EXECUTE_LIST: ExecuteListItem[] = [
|
||||
{
|
||||
id: 'update_start_time',
|
||||
name: 'Update Start Time',
|
||||
description: `Update the start time of the whitelist`,
|
||||
},
|
||||
{
|
||||
id: 'update_end_time',
|
||||
name: 'Update End Time',
|
||||
description: `Update the end time of the whitelist`,
|
||||
},
|
||||
{
|
||||
id: 'add_members',
|
||||
name: 'Add Members',
|
||||
description: `Add members to the whitelist`,
|
||||
},
|
||||
{
|
||||
id: 'remove_members',
|
||||
name: 'Remove Members',
|
||||
description: `Remove members from the whitelist`,
|
||||
},
|
||||
{
|
||||
id: 'update_per_address_limit',
|
||||
name: 'Update Per Address Limit',
|
||||
description: `Update tokens per address limit`,
|
||||
},
|
||||
{
|
||||
id: 'increase_member_limit',
|
||||
name: 'Increase Member Limit',
|
||||
description: `Increase the member limit of the whitelist`,
|
||||
},
|
||||
]
|
||||
|
||||
export interface DispatchExecuteProps {
|
||||
type: ExecuteType
|
||||
[k: string]: unknown
|
||||
}
|
||||
|
||||
type Select<T extends ExecuteType> = T
|
||||
|
||||
/** @see {@link WhiteListInstance} */
|
||||
export type DispatchExecuteArgs = {
|
||||
contract: string
|
||||
messages?: WhiteListInstance
|
||||
} & (
|
||||
| { type: undefined }
|
||||
| { type: Select<'update_start_time'>; timestamp: string }
|
||||
| { type: Select<'update_end_time'>; timestamp: string }
|
||||
| { type: Select<'add_members'>; members: string[] }
|
||||
| { type: Select<'remove_members'>; members: string[] }
|
||||
| { type: Select<'update_per_address_limit'>; limit: number }
|
||||
| { type: Select<'increase_member_limit'>; limit: number }
|
||||
)
|
||||
|
||||
export const dispatchExecute = async (args: DispatchExecuteArgs) => {
|
||||
const { messages } = args
|
||||
if (!messages) {
|
||||
throw new Error('cannot dispatch execute, messages is not defined')
|
||||
}
|
||||
switch (args.type) {
|
||||
case 'update_start_time': {
|
||||
return messages.updateStartTime(args.timestamp)
|
||||
}
|
||||
case 'update_end_time': {
|
||||
return messages.updateEndTime(args.timestamp)
|
||||
}
|
||||
case 'add_members': {
|
||||
return messages.addMembers(args.members)
|
||||
}
|
||||
case 'remove_members': {
|
||||
return messages.removeMembers(args.members)
|
||||
}
|
||||
case 'update_per_address_limit': {
|
||||
return messages.updatePerAddressLimit(args.limit)
|
||||
}
|
||||
case 'increase_member_limit': {
|
||||
return messages.increaseMemberLimit(args.limit)
|
||||
}
|
||||
default: {
|
||||
throw new Error('unknown execute type')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const previewExecutePayload = (args: DispatchExecuteArgs) => {
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
const { messages } = useWhiteListContract()
|
||||
const { contract } = args
|
||||
switch (args.type) {
|
||||
case 'update_start_time': {
|
||||
return messages(contract)?.updateStartTime(args.timestamp)
|
||||
}
|
||||
case 'update_end_time': {
|
||||
return messages(contract)?.updateEndTime(args.timestamp)
|
||||
}
|
||||
case 'add_members': {
|
||||
return messages(contract)?.addMembers(args.members)
|
||||
}
|
||||
case 'remove_members': {
|
||||
return messages(contract)?.removeMembers(args.members)
|
||||
}
|
||||
case 'update_per_address_limit': {
|
||||
return messages(contract)?.updatePerAddressLimit(args.limit)
|
||||
}
|
||||
case 'increase_member_limit': {
|
||||
return messages(contract)?.increaseMemberLimit(args.limit)
|
||||
}
|
||||
default: {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const isEitherType = <T extends ExecuteType>(type: unknown, arr: T[]): type is T => {
|
||||
return arr.some((val) => type === val)
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
import type { WhiteListInstance } from '../contract'
|
||||
|
||||
export type QueryType = typeof QUERY_TYPES[number]
|
||||
|
||||
export const QUERY_TYPES = ['has_started', 'has_ended', 'is_active', 'members', 'has_member', 'config'] as const
|
||||
|
||||
export interface QueryListItem {
|
||||
id: QueryType
|
||||
name: string
|
||||
description?: string
|
||||
}
|
||||
|
||||
export const QUERY_LIST: QueryListItem[] = [
|
||||
{ id: 'has_started', name: 'Has Started', description: 'Check if the whitelist minting has started' },
|
||||
{ id: 'has_ended', name: 'Has Ended', description: 'Check if the whitelist minting has ended' },
|
||||
{ id: 'is_active', name: 'Is Active', description: 'Check if the whitelist minting is active' },
|
||||
{ id: 'members', name: 'Members', description: 'View the whitelist members' },
|
||||
{ id: 'has_member', name: 'Has Member', description: 'Check if a member is in the whitelist' },
|
||||
{ id: 'config', name: 'Config', description: 'View the whitelist configuration' },
|
||||
]
|
||||
|
||||
export interface DispatchQueryProps {
|
||||
messages: WhiteListInstance | undefined
|
||||
type: QueryType
|
||||
address: string
|
||||
}
|
||||
|
||||
export const dispatchQuery = (props: DispatchQueryProps) => {
|
||||
const { messages, type, address } = props
|
||||
switch (type) {
|
||||
case 'has_started':
|
||||
return messages?.hasStarted()
|
||||
case 'has_ended':
|
||||
return messages?.hasEnded()
|
||||
case 'is_active':
|
||||
return messages?.isActive()
|
||||
case 'members':
|
||||
return messages?.members()
|
||||
case 'has_member':
|
||||
return messages?.hasMember(address)
|
||||
case 'config':
|
||||
return messages?.config()
|
||||
default: {
|
||||
throw new Error('unknown query type')
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,33 +1,29 @@
|
||||
import { Coin } from '@cosmjs/proto-signing'
|
||||
import { useWallet } from 'contexts/wallet'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
|
||||
import { WhiteList } from './contract'
|
||||
import {
|
||||
InstantiateResponse,
|
||||
WhiteList as initContract,
|
||||
WhiteListContract,
|
||||
WhiteListInstance,
|
||||
} from './contract'
|
||||
import type { InstantiateResponse, WhiteListContract, WhiteListInstance, WhitelistMessages } from './contract'
|
||||
import { WhiteList as initContract } from './contract'
|
||||
|
||||
export interface useWhiteListContractProps {
|
||||
export interface UseWhiteListContractProps {
|
||||
instantiate: (
|
||||
codeId: number,
|
||||
initMsg: Record<string, unknown>,
|
||||
label: string,
|
||||
admin?: string,
|
||||
funds?: Coin[]
|
||||
) => Promise<InstantiateResponse>
|
||||
|
||||
use: (customAddress: string) => WhiteListInstance | undefined
|
||||
use: (customAddress?: string) => WhiteListInstance | undefined
|
||||
|
||||
updateContractAddress: (contractAddress: string) => void
|
||||
|
||||
messages: (contractAddress: string) => WhitelistMessages | undefined
|
||||
}
|
||||
|
||||
export function useWhiteListContract(): useWhiteListContractProps {
|
||||
export function useWhiteListContract(): UseWhiteListContractProps {
|
||||
const wallet = useWallet()
|
||||
|
||||
const [address, setAddress] = useState<string>('')
|
||||
const [WhiteList, setWhiteList] = useState<WhiteListContract>()
|
||||
const [whiteList, setWhiteList] = useState<WhiteListContract>()
|
||||
|
||||
useEffect(() => {
|
||||
setAddress(localStorage.getItem('contract_address') || '')
|
||||
@@ -35,13 +31,9 @@ export function useWhiteListContract(): useWhiteListContractProps {
|
||||
|
||||
useEffect(() => {
|
||||
if (wallet.initialized) {
|
||||
const getWhiteListInstance = async (): Promise<void> => {
|
||||
const client = wallet.getClient()
|
||||
const whiteListContract = initContract(client, wallet.address)
|
||||
setWhiteList(whiteListContract)
|
||||
}
|
||||
|
||||
getWhiteListInstance()
|
||||
const client = wallet.getClient()
|
||||
const whiteListContract = initContract(client, wallet.address)
|
||||
setWhiteList(whiteListContract)
|
||||
}
|
||||
}, [wallet])
|
||||
|
||||
@@ -50,34 +42,33 @@ export function useWhiteListContract(): useWhiteListContractProps {
|
||||
}
|
||||
|
||||
const instantiate = useCallback(
|
||||
(codeId, initMsg, label, admin?, funds?): Promise<InstantiateResponse> => {
|
||||
(codeId: number, initMsg: Record<string, unknown>, label: string, admin?: string): Promise<InstantiateResponse> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!WhiteList) return reject('Contract is not initialized.')
|
||||
WhiteList.instantiate(
|
||||
wallet.address,
|
||||
codeId,
|
||||
initMsg,
|
||||
label,
|
||||
admin,
|
||||
funds
|
||||
)
|
||||
.then(resolve)
|
||||
.catch(reject)
|
||||
if (!whiteList) {
|
||||
reject(new Error('Contract is not initialized.'))
|
||||
return
|
||||
}
|
||||
whiteList.instantiate(codeId, initMsg, label, admin).then(resolve).catch(reject)
|
||||
})
|
||||
},
|
||||
[WhiteList, wallet]
|
||||
[whiteList],
|
||||
)
|
||||
|
||||
const use = useCallback(
|
||||
(customAddress = ''): WhiteListInstance | undefined => {
|
||||
return WhiteList?.use(address || customAddress)
|
||||
return whiteList?.use(address || customAddress)
|
||||
},
|
||||
[WhiteList]
|
||||
[whiteList, address],
|
||||
)
|
||||
|
||||
const messages = useCallback((): WhitelistMessages | undefined => {
|
||||
return whiteList?.messages(address)
|
||||
}, [whiteList, address])
|
||||
|
||||
return {
|
||||
instantiate,
|
||||
use,
|
||||
updateContractAddress,
|
||||
messages,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user