Skip to content

Commit 24e72da

Browse files
authored
Merge pull request #387 from rabbitholegg/mmackz/zora-create
feat(Zora): add `create` action to Zora plugin
2 parents 8a57a37 + 2a5a478 commit 24e72da

File tree

8 files changed

+178
-8
lines changed

8 files changed

+178
-8
lines changed

.changeset/eleven-dryers-turn.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@rabbitholegg/questdk-plugin-zora": minor
3+
---
4+
5+
add `create` action to zora plugin

packages/zora/src/Zora.test.ts

Lines changed: 63 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
1-
import { getDynamicNameParams, getMintIntent, mint, simulateMint } from './Zora'
2-
import { failingTestCases, passingTestCases } from './test-setup'
1+
import {
2+
create,
3+
getDynamicNameParams,
4+
getMintIntent,
5+
mint,
6+
simulateMint,
7+
} from './Zora'
8+
import {
9+
failingTestCasesCreate,
10+
failingTestCasesMint,
11+
passingTestCasesCreate,
12+
passingTestCasesMint,
13+
} from './test-setup'
314
import {
415
EXPECTED_ENCODED_DATA_721,
516
EXPECTED_ENCODED_DATA_1155,
@@ -16,7 +27,7 @@ import { type Address, parseEther } from 'viem'
1627
import { describe, expect, test, vi } from 'vitest'
1728

1829
describe('Given the zora plugin', () => {
19-
describe('When handling the mint', () => {
30+
describe('When handling the mint action', () => {
2031
describe('should return a valid action filter', () => {
2132
test('when making a valid mint action', async () => {
2233
const filter = await mint({
@@ -44,7 +55,7 @@ describe('Given the zora plugin', () => {
4455
})
4556

4657
describe('should pass filter with valid transactions', () => {
47-
passingTestCases.forEach((testCase) => {
58+
passingTestCasesMint.forEach((testCase) => {
4859
const { transaction, params, description } = testCase
4960
test(description, async () => {
5061
const filter = await mint(params)
@@ -54,7 +65,7 @@ describe('Given the zora plugin', () => {
5465
})
5566

5667
describe('should not pass filter with invalid transactions', () => {
57-
failingTestCases.forEach((testCase) => {
68+
failingTestCasesMint.forEach((testCase) => {
5869
const { transaction, params, description } = testCase
5970
test(description, async () => {
6071
const filter = await mint(params)
@@ -63,6 +74,53 @@ describe('Given the zora plugin', () => {
6374
})
6475
})
6576
})
77+
78+
describe('When handling the create action', () => {
79+
describe('should return a valid action filter', () => {
80+
test('when making a valid create action', async () => {
81+
const filter = await create({
82+
chainId: 1,
83+
})
84+
expect(filter).toBeTypeOf('object')
85+
expect(Number(filter.chainId)).toBe(1)
86+
if (typeof filter.to === 'string') {
87+
expect(filter.to).toMatch(/^0x[a-fA-F0-9]{40}$/)
88+
} else {
89+
// if to is an object, it should have a logical operator as the only key
90+
expect(filter.to).toBeTypeOf('object')
91+
expect(Object.keys(filter.to)).toHaveLength(1)
92+
expect(
93+
['$or', '$and'].some((prop) =>
94+
Object.hasOwnProperty.call(filter.to, prop),
95+
),
96+
).to.be.true
97+
expect(Object.values(filter.to)[0]).to.satisfy((arr: string[]) =>
98+
arr.every((val) => val.match(/^0x[a-fA-F0-9]{40}$/)),
99+
)
100+
}
101+
})
102+
})
103+
104+
describe('should pass filter with valid transactions', () => {
105+
passingTestCasesCreate.forEach((testCase) => {
106+
const { transaction, params, description } = testCase
107+
test(description, async () => {
108+
const filter = await create(params)
109+
expect(apply(transaction, filter)).to.be.true
110+
})
111+
})
112+
})
113+
114+
describe('should not pass filter with invalid transactions', () => {
115+
failingTestCasesCreate.forEach((testCase) => {
116+
const { transaction, params, description } = testCase
117+
test(description, async () => {
118+
const filter = await create(params)
119+
expect(apply(transaction, filter)).to.be.false
120+
})
121+
})
122+
})
123+
})
66124
})
67125

68126
describe('Given the getMintIntent function', () => {

packages/zora/src/Zora.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {
2+
CREATE_CONTRACT_ABI,
23
FUNCTION_SELECTORS,
34
UNIVERSAL_MINTER_ABI,
45
ZORA_MINTER_ABI_721,
@@ -8,10 +9,12 @@ import {
89
import { CHAIN_ID_ARRAY } from './chain-ids'
910
import {
1011
FIXED_PRICE_SALE_STRATS,
12+
ZORA_1155_FACTORY,
1113
ZORA_DEPLOYER_ADDRESS,
1214
} from './contract-addresses'
1315
import {
1416
type MintActionParams,
17+
type CreateActionParams,
1518
type TransactionFilter,
1619
compressJson,
1720
} from '@rabbitholegg/questdk'
@@ -42,6 +45,20 @@ import {
4245
toHex,
4346
} from 'viem'
4447

48+
export const create = async (
49+
create: CreateActionParams,
50+
): Promise<TransactionFilter> => {
51+
const { chainId, contractAddress } = create
52+
53+
return compressJson({
54+
chainId,
55+
to: contractAddress ?? ZORA_1155_FACTORY,
56+
input: {
57+
$abi: CREATE_CONTRACT_ABI,
58+
},
59+
})
60+
}
61+
4562
export const mint = async (
4663
mint: MintActionParams,
4764
): Promise<TransactionFilter> => {

packages/zora/src/abi.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,43 @@ export const UNIVERSAL_MINTER_ABI = [
401401
},
402402
] // universal batch mint
403403

404+
export const CREATE_CONTRACT_ABI = [
405+
{
406+
inputs: [
407+
{ internalType: 'string', name: 'newContractURI', type: 'string' },
408+
{ internalType: 'string', name: 'name', type: 'string' },
409+
{
410+
components: [
411+
{
412+
internalType: 'uint32',
413+
name: 'royaltyMintSchedule',
414+
type: 'uint32',
415+
},
416+
{ internalType: 'uint32', name: 'royaltyBPS', type: 'uint32' },
417+
{
418+
internalType: 'address',
419+
name: 'royaltyRecipient',
420+
type: 'address',
421+
},
422+
],
423+
internalType: 'struct ICreatorRoyaltiesControl.RoyaltyConfiguration',
424+
name: 'defaultRoyaltyConfiguration',
425+
type: 'tuple',
426+
},
427+
{
428+
internalType: 'address payable',
429+
name: 'defaultAdmin',
430+
type: 'address',
431+
},
432+
{ internalType: 'bytes[]', name: 'setupActions', type: 'bytes[]' },
433+
],
434+
name: 'createContract',
435+
outputs: [{ internalType: 'address', name: '', type: 'address' }],
436+
stateMutability: 'nonpayable',
437+
type: 'function',
438+
},
439+
]
440+
404441
export const FUNCTION_SELECTORS = [
405442
'359f1302', // mint (1155)
406443
'731133e9', // mint (Legacy 1155)

packages/zora/src/contract-addresses.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ export const FIXED_PRICE_SALE_STRATS: { [chainId: number]: Address } = {
1010
[Chains.ARBITRUM_ONE]: '0x1Cd1C1f3b8B779B50Db23155F2Cb244FCcA06B21',
1111
}
1212

13+
export const ZORA_1155_FACTORY = '0x777777c338d93e2c7adf08d102d45ca7cc4ed021'
14+
1315
// for referrals
1416
export const ZORA_DEPLOYER_ADDRESS =
1517
'0xe3bBA2A4F8E0F5C32EF5097F988a4d88075C8B48'

packages/zora/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
} from '@rabbitholegg/questdk-plugin-utils'
77

88
import {
9+
create,
910
getDynamicNameParams,
1011
getFees,
1112
getMintIntent,
@@ -21,6 +22,7 @@ export const Zora: IActionPlugin = {
2122
getSupportedTokenAddresses,
2223
getSupportedChainIds,
2324
bridge: async () => new PluginActionNotImplementedError(),
25+
create,
2426
swap: async () => new PluginActionNotImplementedError(),
2527
mint,
2628
getDynamicNameParams,

packages/zora/src/test-setup.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import {
22
BASIC_PURCHASE,
33
BATCH_MINT_ARB,
4+
CREATE_COLLECTION_BASE,
5+
CREATE_COLLECTION_ZORA,
46
LAYER_ZERO_MINT,
57
MINT_BATCH_WITHOUT_FEES,
68
MINT_WITH_REWARDS,
@@ -9,7 +11,7 @@ import {
911
import { createTestCase } from '@rabbitholegg/questdk-plugin-utils'
1012
import { getAddress } from 'viem'
1113

12-
export const passingTestCases = [
14+
export const passingTestCasesMint = [
1315
createTestCase(BASIC_PURCHASE, 'when doing a basic purchase'),
1416
createTestCase(MINT_WITH_REWARDS, 'Minting with rewards'),
1517
createTestCase(MINT_WITH_REWARDS_1155, 'Minting with rewards 1155'),
@@ -29,7 +31,7 @@ export const passingTestCases = [
2931
createTestCase(LAYER_ZERO_MINT, 'using layer zero mint'),
3032
]
3133

32-
export const failingTestCases = [
34+
export const failingTestCasesMint = [
3335
createTestCase(BASIC_PURCHASE, 'when chainId is incorrect', {
3436
chainId: 1,
3537
}),
@@ -60,3 +62,17 @@ export const failingTestCases = [
6062
},
6163
),
6264
]
65+
66+
export const passingTestCasesCreate = [
67+
createTestCase(CREATE_COLLECTION_BASE, 'when creating a collection on BASE'),
68+
createTestCase(CREATE_COLLECTION_ZORA, 'when creating a collection on Zora'),
69+
]
70+
71+
export const failingTestCasesCreate = [
72+
createTestCase(CREATE_COLLECTION_BASE, 'when chainId is incorrect', {
73+
chainId: 1,
74+
}),
75+
createTestCase(CREATE_COLLECTION_ZORA, 'when contractAddress is incorrect', {
76+
contractAddress: '0x4f330940159fB3368F5b06b34212C0cDB4e2C032',
77+
}),
78+
]

packages/zora/src/test-transactions.ts

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
import { type MintActionParams } from '@rabbitholegg/questdk'
1+
import type {
2+
MintActionParams,
3+
CreateActionParams,
4+
} from '@rabbitholegg/questdk'
25
import { Chains, type TestParams } from '@rabbitholegg/questdk-plugin-utils'
36

47
export const BASIC_PURCHASE: TestParams<MintActionParams> = {
@@ -107,3 +110,33 @@ export const LAYER_ZERO_MINT: TestParams<MintActionParams> = {
107110
contractAddress: '0x323c74b3dae9844c113d41e9c3db2743c500a26d',
108111
},
109112
}
113+
114+
export const CREATE_COLLECTION_BASE: TestParams<CreateActionParams> = {
115+
transaction: {
116+
chainId: 8453, // BASE
117+
from: '0xec8287faef6cd7fc9887be6e40d6abc0ccb29d2f',
118+
to: '0x777777c338d93e2c7adf08d102d45ca7cc4ed021',
119+
hash: '0x3ae17f5201c98cdcff8721f4fbf641d19356b00332f605e9d19d915b1e6a1be3',
120+
input:
121+
'0x0582823a00000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001f4000000000000000000000000ec8287faef6cd7fc9887be6e40d6abc0ccb29d2f000000000000000000000000ec8287faef6cd7fc9887be6e40d6abc0ccb29d2f00000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000042697066733a2f2f6261666b726569656435716f7a686578736678376e326a33366b72337573776d69766d7a6b326b686c7263366d796f61726f7a787861787662636d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c42617365f09f94b5f09fa5ba0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000005400000000000000000000000000000000000000000000000000000000000000024e72878b400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4674cbae60000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000ffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000042697066733a2f2f6261666b726569677070737336623676346536346c61787165666c6e6e6c74346c6f6a6b3773676377767237347578707a6f686d627769756a3371000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000084afed7e9e0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001f4000000000000000000000000ec8287faef6cd7fc9887be6e40d6abc0ccb29d2f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000648ec998a0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000004e2516a2c207e84a1839755675dfd8ef6302f0a0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000164d904b94a000000000000000000000000000000000000000000000000000000000000000100000000000000000000000004e2516a2c207e84a1839755675dfd8ef6302f0a000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c434db7eee0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000006644013400000000000000000000000000000000000000000000000000000000666b8e3400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ec8287faef6cd7fc9887be6e40d6abc0ccb29d2f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c4c238d1ee000000000000000000000000ec8287faef6cd7fc9887be6e40d6abc0ccb29d2f0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
122+
value: '0',
123+
},
124+
params: {
125+
chainId: Chains.BASE,
126+
},
127+
}
128+
129+
export const CREATE_COLLECTION_ZORA: TestParams<CreateActionParams> = {
130+
transaction: {
131+
chainId: 7777777, // Zora
132+
from: '0x561db962f06B295cE2A95f31e81Ca5839b7CAfdB',
133+
to: '0x777777C338d93e2C7adf08D102d45CA7CC4Ed021',
134+
hash: '0x391c204dbc67500ef79d460e7ad9870c955c691bef9c5dce76fe6731d3bf5327',
135+
input:
136+
'0x0582823a00000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001f4000000000000000000000000561db962f06b295ce2a95f31e81ca5839b7cafdb000000000000000000000000561db962f06b295ce2a95f31e81ca5839b7cafdb00000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000042697066733a2f2f6261666b72656966366636736e786c7770767a6f36377376707a676c6d716b7335686b77353268706973626f736d646a746977616c366771633571000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000367686b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000005400000000000000000000000000000000000000000000000000000000000000024e72878b400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4674cbae60000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000ffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000042697066733a2f2f6261666b726569676f7472736c37756c65626c373776356a336c7575756c7678356e356879737a626f74657874666b6d6f637836636f7a36746671000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000084afed7e9e0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001f4000000000000000000000000561db962f06b295ce2a95f31e81ca5839b7cafdb0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000648ec998a0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000004e2516a2c207e84a1839755675dfd8ef6302f0a0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000164d904b94a000000000000000000000000000000000000000000000000000000000000000100000000000000000000000004e2516a2c207e84a1839755675dfd8ef6302f0a000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c434db7eee0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000006644203100000000000000000000000000000000000000000000000000000000666bad3100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002cd9760ba5000000000000000000000000000561db962f06b295ce2a95f31e81ca5839b7cafdb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c4c238d1ee000000000000000000000000561db962f06b295ce2a95f31e81ca5839b7cafdb0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
137+
value: '0',
138+
},
139+
params: {
140+
chainId: Chains.ZORA,
141+
},
142+
}

0 commit comments

Comments
 (0)