Skip to content

Commit 5a1ba77

Browse files
Merge remote-tracking branch 'origin/master' into privy-playgroud
2 parents d86bff9 + 84a78cd commit 5a1ba77

File tree

90 files changed

+7364
-3081
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

90 files changed

+7364
-3081
lines changed

ACTIONBUTTON_REFACTOR_PLAN.md

Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
# ActionButtonBody Wallet Connection Refactor Plan
2+
3+
## Problem Statement
4+
5+
The `ActionButtonBody` component is currently tightly coupled to Sequence Connect's `useOpenConnectModal` hook, making it incompatible with other wallet providers like Privy. This causes the error "useGenericContext must be used within a Provider" when used in the Privy playground environment.
6+
7+
## Current Architecture
8+
9+
### ActionButtonBody Dependencies
10+
- **Location**: `sdk/src/react/ui/components/_internals/action-button/components/ActionButtonBody.tsx`
11+
- **Hard Dependency**: `useOpenConnectModal` from `@0xsequence/connect`
12+
- **Usage Pattern**:
13+
1. Check if wallet connected via `useWallet()`
14+
2. If not connected, set pending action and call `setOpenConnectModal(true)`
15+
3. If connected, execute action directly
16+
17+
### Wallet Provider Environments
18+
1. **Sequence Connect**: Uses `SequenceConnectProvider` + `useOpenConnectModal`
19+
2. **Privy**: Uses `PrivyProvider` + `useLogin()` from `@privy-io/react-auth`
20+
3. **Future**: Potentially other wallet providers
21+
22+
## Proposed Solution: Wallet Connection Abstraction
23+
24+
### Phase 1: Create Wallet Connection Context
25+
26+
#### 1.1 Define Wallet Connection Interface
27+
```typescript
28+
// sdk/src/react/_internal/wallet/types.ts
29+
interface WalletConnectionHandler {
30+
openConnectModal: () => void;
31+
isConnected: boolean;
32+
address?: string;
33+
}
34+
```
35+
36+
#### 1.2 Create Wallet Connection Context
37+
```typescript
38+
// sdk/src/react/_internal/wallet/WalletConnectionContext.tsx
39+
const WalletConnectionContext = createContext<WalletConnectionHandler | null>(null);
40+
41+
export const useWalletConnection = () => {
42+
const context = useContext(WalletConnectionContext);
43+
if (!context) {
44+
throw new Error('useWalletConnection must be used within a WalletConnectionProvider');
45+
}
46+
return context;
47+
};
48+
```
49+
50+
#### 1.3 Create Provider Implementations
51+
52+
**Sequence Connect Provider**:
53+
```typescript
54+
// sdk/src/react/_internal/wallet/providers/SequenceWalletConnectionProvider.tsx
55+
export const SequenceWalletConnectionProvider = ({ children }) => {
56+
const { setOpenConnectModal } = useOpenConnectModal();
57+
const { address } = useWallet();
58+
59+
const handler: WalletConnectionHandler = {
60+
openConnectModal: () => setOpenConnectModal(true),
61+
isConnected: !!address,
62+
address
63+
};
64+
65+
return (
66+
<WalletConnectionContext.Provider value={handler}>
67+
{children}
68+
</WalletConnectionContext.Provider>
69+
);
70+
};
71+
```
72+
73+
**Privy Provider**:
74+
```typescript
75+
// sdk/src/react/_internal/wallet/providers/PrivyWalletConnectionProvider.tsx
76+
export const PrivyWalletConnectionProvider = ({ children }) => {
77+
const { login, authenticated } = usePrivy();
78+
const { address } = useAccount();
79+
80+
const handler: WalletConnectionHandler = {
81+
openConnectModal: () => login(),
82+
isConnected: authenticated && !!address,
83+
address
84+
};
85+
86+
return (
87+
<WalletConnectionContext.Provider value={handler}>
88+
{children}
89+
</WalletConnectionContext.Provider>
90+
);
91+
};
92+
```
93+
94+
### Phase 2: Auto-Detection Provider
95+
96+
#### 2.1 Create Smart Provider
97+
```typescript
98+
// sdk/src/react/_internal/wallet/SmartWalletConnectionProvider.tsx
99+
export const SmartWalletConnectionProvider = ({ children }) => {
100+
// Detect which wallet provider is available in the React tree
101+
const hasSequenceConnect = useContext(SequenceConnectContext) !== null;
102+
const hasPrivy = useContext(PrivyContext) !== null;
103+
104+
if (hasSequenceConnect) {
105+
return <SequenceWalletConnectionProvider>{children}</SequenceWalletConnectionProvider>;
106+
}
107+
108+
if (hasPrivy) {
109+
return <PrivyWalletConnectionProvider>{children}</PrivyWalletConnectionProvider>;
110+
}
111+
112+
throw new Error('No supported wallet provider found');
113+
};
114+
```
115+
116+
### Phase 3: Update ActionButtonBody
117+
118+
#### 3.1 Refactor ActionButtonBody
119+
```typescript
120+
// sdk/src/react/ui/components/_internals/action-button/components/ActionButtonBody.tsx
121+
export const ActionButtonBody = ({ action, onClick, tokenId, children }) => {
122+
const { openConnectModal, isConnected } = useWalletConnection();
123+
const { setPendingAction } = useMarketplaceStore();
124+
125+
const handleClick = () => {
126+
if (!isConnected && action) {
127+
setPendingAction(action, onClick, tokenId);
128+
openConnectModal();
129+
} else {
130+
onClick?.();
131+
}
132+
};
133+
134+
return (
135+
<Button onClick={handleClick}>
136+
{children}
137+
</Button>
138+
);
139+
};
140+
```
141+
142+
### Phase 4: Integration Points
143+
144+
#### 4.1 Update MarketplaceProvider
145+
```typescript
146+
// sdk/src/react/ui/components/MarketplaceProvider.tsx
147+
export const MarketplaceProvider = ({ children, config }) => {
148+
return (
149+
<MarketplaceConfigProvider config={config}>
150+
<SmartWalletConnectionProvider>
151+
<MarketplaceStoreProvider>
152+
{children}
153+
</MarketplaceStoreProvider>
154+
</SmartWalletConnectionProvider>
155+
</MarketplaceConfigProvider>
156+
);
157+
};
158+
```
159+
160+
#### 4.2 Update Playground Providers
161+
No changes needed - the auto-detection will handle provider selection.
162+
163+
## Implementation Steps
164+
165+
### Step 1: Foundation (1-2 hours)
166+
- [ ] Create wallet connection types and interfaces
167+
- [ ] Create base WalletConnectionContext
168+
- [ ] Create useWalletConnection hook
169+
170+
### Step 2: Provider Implementations (2-3 hours)
171+
- [ ] Implement SequenceWalletConnectionProvider
172+
- [ ] Implement PrivyWalletConnectionProvider
173+
- [ ] Test both providers in isolation
174+
175+
### Step 3: Auto-Detection (1-2 hours)
176+
- [ ] Implement SmartWalletConnectionProvider
177+
- [ ] Add provider detection logic
178+
- [ ] Handle edge cases and error states
179+
180+
### Step 4: ActionButtonBody Refactor (1 hour)
181+
- [ ] Remove useOpenConnectModal dependency
182+
- [ ] Update to use useWalletConnection
183+
- [ ] Maintain existing functionality
184+
185+
### Step 5: Integration (1 hour)
186+
- [ ] Update MarketplaceProvider
187+
- [ ] Test in both playground environments
188+
- [ ] Verify all collectible actions work
189+
190+
### Step 6: Testing & Validation (2-3 hours)
191+
- [ ] Test all collectible card actions (Buy, Sell, Transfer, etc.)
192+
- [ ] Test wallet connection flows in both environments
193+
- [ ] Test error handling and edge cases
194+
- [ ] Update any related tests
195+
196+
## Benefits
197+
198+
1. **Wallet Provider Agnostic**: ActionButtonBody works with any wallet provider
199+
2. **Zero Breaking Changes**: Existing implementations continue to work
200+
3. **Future Proof**: Easy to add new wallet providers
201+
4. **Clean Architecture**: Clear separation of concerns
202+
5. **Auto-Detection**: No manual configuration required
203+
204+
## Risks & Mitigation
205+
206+
### Risk: Provider Detection Failures
207+
**Mitigation**: Add comprehensive error handling and fallback mechanisms
208+
209+
### Risk: Breaking Changes
210+
**Mitigation**: Maintain backward compatibility through gradual migration
211+
212+
### Risk: Performance Impact
213+
**Mitigation**: Use React context efficiently, avoid unnecessary re-renders
214+
215+
## Alternative Approaches Considered
216+
217+
### Option A: Configuration-Based
218+
Add wallet connection config to SDK config. **Rejected**: Requires manual configuration.
219+
220+
### Option B: Hook-Based Only
221+
Create useWalletConnection without context. **Rejected**: Harder to manage state across components.
222+
223+
### Option C: Component Props
224+
Pass connection handler as props. **Rejected**: Requires changes to all parent components.
225+
226+
## Success Criteria
227+
228+
- [ ] Privy playground collectibles page loads without errors
229+
- [ ] All collectible actions work in both Sequence and Privy environments
230+
- [ ] No breaking changes to existing implementations
231+
- [ ] Clean, maintainable code architecture
232+
- [ ] Comprehensive test coverage
233+
234+
## Timeline
235+
236+
**Total Estimated Time**: 8-12 hours
237+
**Target Completion**: 1-2 days
238+
239+
This refactor will make the ActionButtonBody component truly wallet-agnostic while maintaining full backward compatibility and enabling future wallet provider integrations.

biome.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"$schema": "https://biomejs.dev/schemas/2.0.0/schema.json",
2+
"$schema": "https://biomejs.dev/schemas/2.0.5/schema.json",
33
"vcs": {
44
"enabled": false,
55
"clientKind": "git",

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
"test": "pnpm run --r --filter \"./sdk\" test",
2222
"coverage": "pnpm run --r --filter \"./sdk\" coverage"
2323
},
24-
"packageManager": "[email protected].1",
24+
"packageManager": "[email protected].3",
2525
"engines": {
2626
"node": "24.x"
2727
},
@@ -30,13 +30,13 @@
3030
"@0xsequence/marketplace-sdk": "workspace:*"
3131
},
3232
"onlyBuiltDependencies": [
33-
"@tailwindcss/oxide",
33+
"lefthook",
3434
"msw"
3535
]
3636
},
3737
"devDependencies": {
3838
"@biomejs/biome": "catalog:",
39-
"@types/node": "^24.0.3",
39+
"@types/node": "^24.0.4",
4040
"knip": "^5.61.2",
4141
"lefthook": "^1.11.14",
4242
"typescript": "catalog:"

playgrounds/next/package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,26 +23,26 @@
2323
"@0xsequence/metadata": "catalog:",
2424
"@0xsequence/network": "catalog:",
2525
"@0xsequence/wallet-widget": "catalog:",
26-
"@tailwindcss/postcss": "^4.1.10",
26+
"@tailwindcss/postcss": "0.0.0-insiders.aa85931",
2727
"@tanstack/react-query": "catalog:",
2828
"@tanstack/react-query-devtools": "catalog:",
2929
"date-fns": "catalog:",
3030
"dnum": "catalog:",
31-
"motion": "^12.18.1",
31+
"motion": "^12.19.1",
3232
"next": "^15.3.4",
3333
"nuqs": "catalog:",
3434
"postcss": "^8.5.6",
3535
"react": "catalog:",
3636
"react-dom": "catalog:",
3737
"react-virtuoso": "^4.13.0",
3838
"shared-components": "workspace:*",
39-
"tailwindcss": "^4.1.10",
39+
"tailwindcss": "0.0.0-insiders.aa85931",
4040
"viem": "catalog:",
4141
"wagmi": "catalog:"
4242
},
4343
"devDependencies": {
4444
"@biomejs/biome": "catalog:",
45-
"@types/node": "^20.19.1",
45+
"@types/node": "^22.15.33",
4646
"@types/react": "catalog:",
4747
"@types/react-dom": "catalog:",
4848
"typescript": "catalog:"

playgrounds/react-vite/package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,28 +23,28 @@
2323
"@0xsequence/metadata": "catalog:",
2424
"@0xsequence/network": "catalog:",
2525
"@legendapp/state": "catalog:",
26-
"@tailwindcss/vite": "^4.1.10",
26+
"@tailwindcss/vite": "0.0.0-insiders.aa85931",
2727
"@tanstack/react-query": "catalog:",
2828
"@tanstack/react-query-devtools": "catalog:",
29-
"@xstate/store": "^3.6.2",
29+
"@xstate/store": "^3.7.0",
3030
"date-fns": "catalog:",
3131
"dnum": "catalog:",
32-
"motion": "^12.18.1",
32+
"motion": "^12.19.1",
3333
"nuqs": "catalog:",
3434
"react": "^19.1.0",
3535
"react-dom": "^19.1.0",
3636
"react-router": "^7.6.2",
3737
"react-virtuoso": "^4.13.0",
3838
"shared-components": "workspace:*",
39-
"tailwindcss": "catalog:",
39+
"tailwindcss": "0.0.0-insiders.aa85931",
4040
"viem": "catalog:",
4141
"wagmi": "catalog:"
4242
},
4343
"devDependencies": {
4444
"@biomejs/biome": "catalog:",
4545
"@types/react": "catalog:",
4646
"@types/react-dom": "catalog:",
47-
"@vitejs/plugin-react": "^4.5.2",
47+
"@vitejs/plugin-react": "^4.6.0",
4848
"typescript": "catalog:",
4949
"vite": "catalog:",
5050
"vite-tsconfig-paths": "catalog:"

playgrounds/shared/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@
3232
"dependencies": {
3333
"@radix-ui/react-accordion": "^1.2.11",
3434
"@tailwindcss/postcss": "^4.1.10",
35-
"@tailwindcss/vite": "^4.1.10",
35+
"@tailwindcss/vite": "0.0.0-insiders.aa85931",
36+
"@tanstack/react-virtual": "^3.13.11",
3637
"date-fns": "^4.1.0",
37-
"postcss": "^8.5.6",
38-
"react-virtuoso": "^4.13.0"
38+
"postcss": "^8.5.6"
3939
}
4040
}

playgrounds/shared/src/components/collectibles/GridContainer.tsx

Lines changed: 0 additions & 35 deletions
This file was deleted.

0 commit comments

Comments
 (0)