Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into mmackz/referral/sound…
Browse files Browse the repository at this point in the history
…-externallink
  • Loading branch information
mmackz committed Jul 16, 2024
2 parents 506f1bf + 1f3dfb0 commit f0efba1
Show file tree
Hide file tree
Showing 15 changed files with 315 additions and 19 deletions.
5 changes: 5 additions & 0 deletions .changeset/light-rabbits-develop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@rabbitholegg/questdk-plugin-pods": minor
---

implement getExternalUrl for pods
5 changes: 5 additions & 0 deletions .changeset/lovely-pans-approve.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@rabbitholegg/questdk-plugin-manifold": minor
---

implement getExternalUrl function
5 changes: 5 additions & 0 deletions .changeset/two-comics-explain.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@rabbitholegg/questdk-plugin-soundxyz": minor
---

use referral param in validation and mint simulation
5 changes: 5 additions & 0 deletions .changeset/warm-insects-lick.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@rabbitholegg/questdk-plugin-pods": minor
---

use referral param in validation
40 changes: 38 additions & 2 deletions packages/manifold/src/Manifold.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import { getFees, getMintIntent, mint, simulateMint } from './Manifold'
import {
getExternalUrl,
getFees,
getMintIntent,
mint,
simulateMint,
} from './Manifold'
import { ERC721_CONTRACT, ERC1155_CONTRACT } from './constants'
import { failingTestCases, passingTestCases } from './test-transactions'
import { apply } from '@rabbitholegg/questdk'
Expand All @@ -8,7 +14,7 @@ import {
type MintIntentParams,
} from '@rabbitholegg/questdk-plugin-utils'
import axios from 'axios'
import { type Address, parseEther } from 'viem'
import { type Address, parseEther, getAddress } from 'viem'
import { MockedFunction, beforeEach, describe, expect, test, vi } from 'vitest'

vi.mock('axios', () => {
Expand Down Expand Up @@ -218,3 +224,33 @@ describe('simulateMint function', () => {
expect(request.value).toBe(value)
})
})

describe('getExternalUrl function', () => {
beforeEach(() => {
vi.resetAllMocks()
})
test('should return the correct url for a 721 mint', async () => {
const mint = {
chainId: Chains.OPTIMISM,
contractAddress: getAddress('0x6935cd348193bab133f3081f53eb99ee6f0d685b'),
}
;(axios.get as MockedFunction<typeof axios.get>).mockResolvedValue({
status: 200,
data: {
slug: 'girls-man',
},
})

const result = await getExternalUrl(mint)
expect(result).toBe('https://app.manifold.xyz/c/girls-man')
})

test('should return the fallback url for an unknown contract', async () => {
const mint = {
chainId: Chains.OPTIMISM,
contractAddress: getAddress('0x7935cd348193bab133f3081f53eb99ee6f0d685b'),
}
const result = await getExternalUrl(mint)
expect(result).toBe('https://app.manifold.xyz/')
})
})
35 changes: 35 additions & 0 deletions packages/manifold/src/Manifold.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,41 @@ export const getFees = async (
}
}

export const getExternalUrl = async (
mint: MintActionParams,
): Promise<string> => {
const { chainId, contractAddress, tokenId } = mint

const baseUrl = 'https://app.manifold.xyz/'

try {
const instanceId = await getInstanceId(
chainId,
contractAddress,
tokenId ?? 1,
)

const { data } = await axios.get<{ slug?: string }>(
`https://apps.api.manifoldxyz.dev/public/instance/data?id=${instanceId}`,
)
const slug = data.slug

if (!slug) {
throw new Error('Slug not found in response')
}

return `${baseUrl}c/${slug}`
} catch (err) {
if (err instanceof Error) {
console.error(err.message)
} else {
console.error(err)
}
// fallback to default manifold url
return baseUrl
}
}

export const getSupportedTokenAddresses = async (
_chainId: number,
): Promise<Address[]> => {
Expand Down
3 changes: 3 additions & 0 deletions packages/manifold/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type {
} from '@rabbitholegg/questdk'

import {
getExternalUrl,
getFees,
getMintIntent,
getProjectFees,
Expand All @@ -23,6 +24,8 @@ export const Manifold: IActionPlugin = {
getProjectFees(params as unknown as MintActionParams),
getFees: async (params: ActionParams) =>
getFees(params as unknown as MintActionParams),
getExternalUrl: async (params: ActionParams) =>
getExternalUrl(params as unknown as MintActionParams),
getMintIntent,
simulateMint,
}
57 changes: 55 additions & 2 deletions packages/pods/src/Pods.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ import {
type MintIntentParams,
} from '@rabbitholegg/questdk-plugin-utils'
import { apply } from '@rabbitholegg/questdk'
import { type Address, parseEther } from 'viem'
import { type Address, parseEther, getAddress, zeroAddress } from 'viem'
import { describe, expect, test, vi } from 'vitest'
import { getMintIntent, mint } from './Pods'
import { getExternalUrl, getMintIntent, mint } from './Pods'
import { failingTestCases, passingTestCases } from './test-setup'
import { EXPECTED_ENCODED_DATA_1155 } from './test-transactions'
import { ZORA_DEPLOYER_ADDRESS } from './contract-addresses'

describe('Given the pods plugin', () => {
describe('When handling the mint', () => {
Expand Down Expand Up @@ -79,6 +80,7 @@ describe('Given the getMintIntent function', () => {
contractAddress: CONTRACT_ADDRESS,
amount: BigInt('10'),
recipient: RECIPIENT_ADDRESS,
referral: '0xe3bba2a4f8e0f5c32ef5097f988a4d88075c8b48',
}

const result = await getMintIntent(mint)
Expand Down Expand Up @@ -124,6 +126,7 @@ describe('simulateMint function', () => {
tokenId: 1,
amount: BigInt(1),
recipient: '0xf70da97812CB96acDF810712Aa562db8dfA3dbEF',
referral: '0xe3bba2a4f8e0f5c32ef5097f988a4d88075c8b48',
}
const value = parseEther('0.0007')
const address = mint.recipient as Address
Expand Down Expand Up @@ -165,6 +168,7 @@ describe('simulateMint function', () => {
contractAddress: '0x7e0b40af1d6f26f2141b90170c513e57b5edd74e',
amount: BigInt(1),
recipient: '0xf70da97812CB96acDF810712Aa562db8dfA3dbEF',
referral: '0xe3bba2a4f8e0f5c32ef5097f988a4d88075c8b48',
}
const value = parseEther('0.0007')
const address = mint.recipient as Address
Expand Down Expand Up @@ -201,3 +205,52 @@ describe('simulateMint function', () => {
expect(request.value).toBe(value)
})
})

describe('getExternalUrl function', () => {
test('should return correct url for mint w/tokenId and referral', async () => {
const params = {
chainId: Chains.BASE,
contractAddress: getAddress('0x7e0b40af1d6f26f2141b90170c513e57b5edd74e'),
tokenId: 21,
referral: getAddress('0x1234567890123456789012345678901234567890'),
}
const result = await getExternalUrl(params)
expect(result).toBe(
'https://pods.media/mint-podcast/why-social-needs-a-layer-2-ft-ryan-li-of-cyber?referrer=0x1234567890123456789012345678901234567890',
)
})

test('should return correct url for mint w/tokenId and w/o referral', async () => {
const params = {
chainId: Chains.BASE,
contractAddress: getAddress('0x7e0b40af1d6f26f2141b90170c513e57b5edd74e'),
tokenId: 21,
}
const result = await getExternalUrl(params)
expect(result).toBe(
`https://pods.media/mint-podcast/why-social-needs-a-layer-2-ft-ryan-li-of-cyber?referrer=${ZORA_DEPLOYER_ADDRESS}`,
)
})

test('should return correct url for mint w/out tokenId', async () => {
const params = {
chainId: Chains.BASE,
contractAddress: getAddress('0x7e0b40af1d6f26f2141b90170c513e57b5edd74e'),
referral: getAddress('0x1234567890123456789012345678901234567890'),
}
const result = await getExternalUrl(params)
expect(result).toBe(
'https://pods.media/mint-podcast?referrer=0x1234567890123456789012345678901234567890',
)
})

test('should return fallback url if error occurs', async () => {
const params = {
chainId: Chains.BASE,
contractAddress: zeroAddress,
referral: getAddress('0x1234567890123456789012345678901234567890'),
}
const result = await getExternalUrl(params)
expect(result).toBe('https://pods.media')
})
})
66 changes: 60 additions & 6 deletions packages/pods/src/Pods.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import axios from 'axios'
import { FEES_ABI, ZORA_MINTER_ABI_1155 } from './abi'
import { CHAIN_ID_ARRAY } from './chain-ids'
import {
FIXED_PRICE_SALE_STRATS,
ZORA_DEPLOYER_ADDRESS,
} from './contract-addresses'
import { type AndArrayItem, getLatestTokenId } from './utils'
import { type AndArrayItem, getLatestTokenId, getUri } from './utils'
import {
type MintActionParams,
type TransactionFilter,
Expand All @@ -26,20 +27,33 @@ import {
type TransactionRequest,
createPublicClient,
encodeFunctionData,
getAddress,
pad,
parseEther,
} from 'viem'

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

const andArray1155: AndArrayItem[] = [
{
quantity: formatAmount(amount),
},
]
if (referral) {
const referralAddress = getAddress(referral)
andArray1155.push({
$or: [
{ mintReferral: referralAddress },
{
rewardsRecipients: [referralAddress],
},
],
})
}
if (recipient) {
andArray1155.push({
minterArguments: {
Expand Down Expand Up @@ -68,17 +82,21 @@ export const mint = async (
export const getMintIntent = async (
mint: MintIntentParams,
): Promise<TransactionRequest> => {
const { chainId, contractAddress, tokenId, amount, recipient } = mint
const { chainId, contractAddress, tokenId, amount, recipient, referral } =
mint

const fixedPriceSaleStratAddress = FIXED_PRICE_SALE_STRATS[chainId]

const _tokenId = tokenId ?? (await getLatestTokenId(contractAddress, chainId))
const referralAddress = referral
? getAddress(referral)
: ZORA_DEPLOYER_ADDRESS

const mintArgs = [
fixedPriceSaleStratAddress,
_tokenId,
amount,
[ZORA_DEPLOYER_ADDRESS],
[referralAddress],
pad(recipient),
]

Expand All @@ -101,7 +119,8 @@ export const simulateMint = async (
account?: Address,
client?: PublicClient,
): Promise<SimulateContractReturnType> => {
const { chainId, contractAddress, tokenId, amount, recipient } = mint
const { chainId, contractAddress, tokenId, amount, recipient, referral } =
mint
const _client =
client ??
(createPublicClient({
Expand All @@ -115,12 +134,15 @@ export const simulateMint = async (
}

const fixedPriceSaleStratAddress = FIXED_PRICE_SALE_STRATS[chainId]
const referralAddress = referral
? getAddress(referral)
: ZORA_DEPLOYER_ADDRESS

const mintArgs = [
fixedPriceSaleStratAddress,
_tokenId,
amount,
[ZORA_DEPLOYER_ADDRESS],
[referralAddress],
pad(recipient),
]
const result = await _client.simulateContract({
Expand Down Expand Up @@ -180,6 +202,38 @@ export const getFees = async (
}
}

export const getExternalUrl = async (
params: MintActionParams,
): Promise<string> => {
const { chainId, contractAddress, tokenId, referral } = params

try {
const client = createPublicClient({
chain: chainIdToViemChain(chainId),
transport: http(),
}) as PublicClient

const uri = await getUri(client, contractAddress, tokenId)
const cid = uri.split('/').slice(2).join('/')

const { data } = await axios.get(`https://arweave.net/${cid}`)

// different properties depending on uri function. One of these will be defined
const baseUrl = data.external_link ?? data.external_url

return `${baseUrl}?referrer=${referral ?? ZORA_DEPLOYER_ADDRESS}`
} catch (error) {
console.error('an error occurred fetching data from the contract')
if (error instanceof Error) {
console.error(error.message)
} else {
console.error(error)
}
// fallback to default pods url
return 'https://pods.media'
}
}

export const getSupportedTokenAddresses = async (
_chainId: number,
): Promise<Address[]> => {
Expand Down
5 changes: 4 additions & 1 deletion packages/pods/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@ import {
} from '@rabbitholegg/questdk-plugin-utils'

import {
getExternalUrl,
getFees,
getMintIntent,
getProjectFees,
getSupportedChainIds,
getSupportedTokenAddresses,
mint,
simulateMint,
} from './Pods.js'
} from './Pods'

export const Pods: IActionPlugin = {
pluginId: 'pods',
Expand All @@ -24,6 +25,8 @@ export const Pods: IActionPlugin = {
mint,
getProjectFees: async (params: ActionParams) =>
getProjectFees(params as unknown as MintActionParams),
getExternalUrl: async (params: ActionParams) =>
getExternalUrl(params as unknown as MintActionParams),
getFees: async (params: ActionParams) =>
getFees(params as unknown as MintActionParams),
getMintIntent,
Expand Down
Loading

0 comments on commit f0efba1

Please sign in to comment.