Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

fix(fabric): fix amount zero issue #473

Merged
merged 2 commits into from
Aug 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/short-roses-pull.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@rabbitholegg/questdk-plugin-fabric": minor
---

fix amount zero issue
17 changes: 11 additions & 6 deletions packages/fabric/src/Fabric.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
Chains,
type MintIntentParams,
} from '@rabbitholegg/questdk-plugin-utils'
import { apply } from '@rabbitholegg/questdk/filter'
import { apply } from '@rabbitholegg/questdk'
import { type Address } from 'viem'
import { describe, expect, test } from 'vitest'

Expand All @@ -13,11 +13,11 @@ describe('Given the fabric plugin', () => {
describe('should return a valid action filter', () => {
test('when making a valid mint action', async () => {
const filter = await mint({
chainId: 1,
contractAddress: '0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF',
chainId: 8453,
contractAddress: '0x2efc6064239121d1d7efb503355daa82b87ee89c',
})
expect(filter).toBeTypeOf('object')
expect(Number(filter.chainId)).toBe(1)
expect(Number(filter.chainId)).toBe(8453)
if (typeof filter.to === 'string') {
expect(filter.to).toMatch(/^0x[a-fA-F0-9]{40}$/)
} else {
Expand Down Expand Up @@ -57,8 +57,13 @@ describe('Given the fabric plugin', () => {
failingTestCases.forEach((testCase) => {
const { transaction, description, params } = testCase
test(description, async () => {
const filter = await mint(params)
expect(apply(transaction, filter)).to.be.false
try {
const filter = await mint(params)
const result = apply(transaction, filter)
expect(result).toBe(false)
} catch (error) {
expect(error).toBeInstanceOf(Error)
}
})
})
})
Expand Down
76 changes: 60 additions & 16 deletions packages/fabric/src/Fabric.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,60 @@
import { FABRIC_ABI } from './abi'
import { FABRIC_MINT_ABI, FABRIC_MINTFOR_ABI } from './abi'
import { getContractData } from './utils'
import {
type MintActionParams,
type TransactionFilter,
compressJson,
GreaterThanOrEqual,
} from '@rabbitholegg/questdk'
import {
Chains,
DEFAULT_ACCOUNT,
chainIdToViemChain,
getMintAmount,
type MintIntentParams,
} from '@rabbitholegg/questdk-plugin-utils'
import {
type Address,
type PublicClient,
type SimulateContractReturnType,
type TransactionRequest,
createPublicClient,
encodeFunctionData,
http,
zeroAddress,
} from 'viem'

export const mint = async (
mint: MintActionParams,
): Promise<TransactionFilter> => {
const { chainId, contractAddress, recipient } = mint
const { chainId, contractAddress, amount, recipient } = mint

const { minPurchaseSeconds, tps } = await getContractData(
chainId,
contractAddress,
)

if (minPurchaseSeconds == null || tps == null) {
throw new Error('Contract data not found')
}

const numTokens = minPurchaseSeconds * tps * getMintAmount(amount)

return compressJson({
chainId,
to: contractAddress,
input: {
$abi: FABRIC_ABI,
account: recipient,
$or: [
{
$abi: FABRIC_MINT_ABI,
numTokens: GreaterThanOrEqual(numTokens),
},
{
$abi: FABRIC_MINTFOR_ABI,
numTokens: GreaterThanOrEqual(numTokens),
account: recipient,
},
],
},
})
}
Expand All @@ -54,9 +80,13 @@ export const getFees = async (
throw new Error('ERC20 not supported')
}

const mintUnits = typeof amount === 'number' ? BigInt(amount) : BigInt(1)
if (!minPurchaseSeconds || !tps) {
throw new Error('Contract data not found')
}

const mintUnits = getMintAmount(amount)

const mintCost = (minPurchaseSeconds as bigint) * (tps as bigint) * mintUnits
const mintCost = minPurchaseSeconds * tps * mintUnits

return { actionFee: mintCost, projectFee: BigInt(0) }
}
Expand All @@ -75,10 +105,14 @@ export const getMintIntent = async (
throw new Error('ERC20 not supported')
}

const mintArgs = [(minPurchaseSeconds as bigint) * (tps as bigint) * amount]
if (!minPurchaseSeconds || !tps) {
throw new Error('Contract data not found')
}

const mintArgs = [minPurchaseSeconds * tps * getMintAmount(amount)]

const data = encodeFunctionData({
abi: FABRIC_ABI,
abi: FABRIC_MINT_ABI,
functionName: 'mint',
args: mintArgs,
})
Expand All @@ -98,25 +132,35 @@ export const simulateMint = async (
): Promise<SimulateContractReturnType> => {
const { chainId, contractAddress, amount } = mint

const _client =
client ??
createPublicClient({
chain: chainIdToViemChain(chainId),
transport: http(),
})

const from = account ?? DEFAULT_ACCOUNT
const {
erc20Address,
minPurchaseSeconds,
tps,
client: _client,
} = await getContractData(chainId, contractAddress, client)
const { erc20Address, minPurchaseSeconds, tps } = await getContractData(
chainId,
contractAddress,
client,
)

// fail simulation if erc20 is used
if (erc20Address !== zeroAddress) {
throw new Error('ERC20 not supported')
}

const mintArgs = [(minPurchaseSeconds as bigint) * (tps as bigint) * amount]
if (!minPurchaseSeconds || !tps) {
throw new Error('Contract data not found')
}

const mintArgs = [minPurchaseSeconds * tps * getMintAmount(amount)]

const result = await _client.simulateContract({
address: contractAddress,
value,
abi: FABRIC_ABI,
abi: FABRIC_MINT_ABI,
functionName: 'mint',
args: mintArgs,
account: from,
Expand Down
35 changes: 19 additions & 16 deletions packages/fabric/src/abi.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export const FABRIC_ABI = [
export const FABRIC_MINT_ABI = [
{
inputs: [
{
Expand All @@ -15,40 +15,43 @@ export const FABRIC_ABI = [
{
inputs: [
{
internalType: 'address',
name: 'account',
type: 'address',
internalType: 'uint256',
name: 'numTokens',
type: 'uint256',
},
{
internalType: 'uint256',
name: 'numTokens',
name: 'referralCode',
type: 'uint256',
},
{
internalType: 'address',
name: 'referrer',
type: 'address',
},
],
name: 'mintFor',
name: 'mintWithReferral',
outputs: [],
stateMutability: 'payable',
type: 'function',
},
]

export const FABRIC_MINTFOR_ABI = [
{
inputs: [
{
internalType: 'uint256',
name: 'numTokens',
type: 'uint256',
internalType: 'address',
name: 'account',
type: 'address',
},
{
internalType: 'uint256',
name: 'referralCode',
name: 'numTokens',
type: 'uint256',
},
{
internalType: 'address',
name: 'referrer',
type: 'address',
},
],
name: 'mintWithReferral',
name: 'mintFor',
outputs: [],
stateMutability: 'payable',
type: 'function',
Expand Down
10 changes: 4 additions & 6 deletions packages/fabric/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ import { type Address, type PublicClient, createPublicClient, http } from 'viem'

interface ContractData {
erc20Address: Address
minPurchaseSeconds: bigint
tps: bigint
client: PublicClient
minPurchaseSeconds: bigint | undefined
tps: bigint | undefined
}

export async function getContractData(
Expand Down Expand Up @@ -38,8 +37,7 @@ export async function getContractData(

return {
erc20Address: erc20Address as Address,
minPurchaseSeconds: minPurchaseSeconds as bigint,
tps: tps as bigint,
client: client as PublicClient,
minPurchaseSeconds: minPurchaseSeconds as bigint | undefined,
tps: tps as bigint | undefined,
}
}
Loading