@goodz-core/sdk 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +271 -83
- package/dist/alive/index.d.ts +175 -0
- package/dist/alive/index.js +4 -0
- package/dist/alive/index.js.map +1 -0
- package/dist/chunk-4SU7SU7K.js +227 -0
- package/dist/chunk-4SU7SU7K.js.map +1 -0
- package/dist/chunk-JAVMQXJM.js +27 -0
- package/dist/chunk-JAVMQXJM.js.map +1 -0
- package/dist/chunk-KLMCZG4N.js +102 -0
- package/dist/chunk-KLMCZG4N.js.map +1 -0
- package/dist/chunk-OUKZ2PRD.js +37 -0
- package/dist/chunk-OUKZ2PRD.js.map +1 -0
- package/dist/chunk-V73MMKHI.js +56 -0
- package/dist/chunk-V73MMKHI.js.map +1 -0
- package/dist/commerce/index.d.ts +462 -0
- package/dist/commerce/index.js +4 -0
- package/dist/commerce/index.js.map +1 -0
- package/dist/core/index.d.ts +76 -385
- package/dist/core/index.js +5 -1
- package/dist/exchange/index.d.ts +252 -0
- package/dist/exchange/index.js +4 -0
- package/dist/exchange/index.js.map +1 -0
- package/dist/index.d.ts +31 -4
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/transport-BOlScYEv.d.ts +377 -0
- package/package.json +20 -3
- package/dist/chunk-G7NKU6PT.js +0 -183
- package/dist/chunk-G7NKU6PT.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @goodz-core/sdk
|
|
2
2
|
|
|
3
|
-
Official SDK for **GoodZ
|
|
3
|
+
Official SDK for the **GoodZ** ecosystem — a unified, type-safe API client for building GoodZ-powered applications. One package covers all five products: Core, Commerce, Exchange, Alive, and Shops. Stripe-style namespaces route requests to the correct service transparently.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -10,7 +10,7 @@ npm install @goodz-core/sdk
|
|
|
10
10
|
pnpm add @goodz-core/sdk
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
Runtime dependency: `superjson` only. Works in Node.js 18+, Deno, Bun, Cloudflare Workers, and browsers (any runtime with Fetch API).
|
|
14
14
|
|
|
15
15
|
## Quick Start
|
|
16
16
|
|
|
@@ -21,11 +21,9 @@ const goodz = createGoodZClient({
|
|
|
21
21
|
accessToken: "your-jwt-token",
|
|
22
22
|
});
|
|
23
23
|
|
|
24
|
-
//
|
|
24
|
+
// Core — settlement
|
|
25
25
|
const balance = await goodz.zcoin.getMyBalance();
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const result = await goodz.zcoin.commercialTransfer({
|
|
26
|
+
const trade = await goodz.zcoin.commercialTransfer({
|
|
29
27
|
instanceId: 90447,
|
|
30
28
|
buyerUserId: 1,
|
|
31
29
|
sellerUserId: 2,
|
|
@@ -34,118 +32,271 @@ const result = await goodz.zcoin.commercialTransfer({
|
|
|
34
32
|
referenceId: "order-abc-123",
|
|
35
33
|
appClientId: "od_myapp",
|
|
36
34
|
});
|
|
37
|
-
|
|
35
|
+
|
|
36
|
+
// Commerce — create a shop and launch a campaign
|
|
37
|
+
const shop = await goodz.commerce.createShop({ name: "Frostpeak Store" });
|
|
38
|
+
const campaign = await goodz.commerce.launchCampaign({ shopId: shop.id, name: "Spring Drop" });
|
|
39
|
+
const order = await goodz.commerce.executePurchase({ campaignId: campaign.id, quantity: 1 });
|
|
40
|
+
|
|
41
|
+
// Exchange — list an item for sale
|
|
42
|
+
const listing = await goodz.exchange.createListing({
|
|
43
|
+
instanceId: 42,
|
|
44
|
+
listingType: "fixed_price",
|
|
45
|
+
askPrice: 2000,
|
|
46
|
+
});
|
|
47
|
+
const data = await goodz.exchange.getMarketData({ coreGoodzId: 42 });
|
|
48
|
+
|
|
49
|
+
// Alive — chat with a character
|
|
50
|
+
const reply = await goodz.alive.sendMessage({
|
|
51
|
+
instanceId: 1,
|
|
52
|
+
userId: 1,
|
|
53
|
+
message: "What's your favorite memory?",
|
|
54
|
+
});
|
|
38
55
|
```
|
|
39
56
|
|
|
40
57
|
## Architecture
|
|
41
58
|
|
|
42
|
-
The SDK is
|
|
59
|
+
The SDK is built on three principles:
|
|
43
60
|
|
|
44
|
-
**
|
|
61
|
+
**One client, all services.** `createGoodZClient()` returns a single object with namespaces for every GoodZ product. Core uses tRPC HTTP wire protocol; sub-sites (Commerce, Exchange, Alive) use MCP JSON-RPC 2.0. The client handles routing transparently — developers never need to know which protocol a method uses.
|
|
45
62
|
|
|
46
|
-
**Hand-crafted types as API contract.** All input/output types are defined inside the SDK itself
|
|
63
|
+
**Hand-crafted types as API contract.** All input/output types are defined inside the SDK itself, mirroring the Zod schemas on Core and the MCP tool schemas on sub-sites. This is the same approach used by the Stripe SDK — types serve as both documentation and compile-time contract. When any service's API evolves, the SDK types are updated and a new version is published.
|
|
47
64
|
|
|
48
|
-
**
|
|
65
|
+
**Zero tRPC dependency.** The SDK speaks the tRPC wire protocol directly using `fetch` + `superjson`, and speaks MCP JSON-RPC natively. Consumers never need to install `@trpc/client`, `@trpc/server`, or any MCP client library.
|
|
49
66
|
|
|
50
|
-
##
|
|
51
|
-
|
|
52
|
-
### Client Configuration
|
|
67
|
+
## Client Configuration
|
|
53
68
|
|
|
54
69
|
```ts
|
|
55
70
|
interface GoodZClientConfig {
|
|
56
71
|
coreUrl?: string; // Default: "https://goodzcore.manus.space"
|
|
72
|
+
commerceUrl?: string; // Default: "https://goodzcommerce.manus.space"
|
|
73
|
+
exchangeUrl?: string; // Default: "https://goodzexchange.manus.space"
|
|
74
|
+
aliveUrl?: string; // Default: "https://goodzalive.manus.space"
|
|
57
75
|
accessToken?: string; // Static JWT token
|
|
58
76
|
getAccessToken?: () => string | Promise<string>; // Dynamic token provider
|
|
59
77
|
headers?: Record<string, string>; // Custom headers for every request
|
|
60
78
|
}
|
|
61
79
|
```
|
|
62
80
|
|
|
63
|
-
The `getAccessToken` function takes precedence over `accessToken` when both are provided. Use it for auto-refresh scenarios.
|
|
81
|
+
The `getAccessToken` function takes precedence over `accessToken` when both are provided. Use it for auto-refresh scenarios. Sub-site URLs default to production endpoints and rarely need to be changed.
|
|
64
82
|
|
|
65
|
-
|
|
83
|
+
## API Reference — Core Namespaces
|
|
66
84
|
|
|
67
|
-
|
|
85
|
+
Core namespaces communicate via tRPC HTTP wire protocol with `goodzcore.manus.space`.
|
|
68
86
|
|
|
69
|
-
|
|
87
|
+
### `goodz.zcoin` — Z-coin Payment & Settlement
|
|
70
88
|
|
|
71
89
|
| Method | Type | Description |
|
|
72
90
|
|--------|------|-------------|
|
|
73
|
-
| `getMyBalance()` | Query |
|
|
74
|
-
| `getMyHistory(input?)` | Query |
|
|
75
|
-
| `getDepositPackages(input?)` | Query |
|
|
76
|
-
| `createDepositOrder(input)` | Mutation | Create
|
|
91
|
+
| `getMyBalance()` | Query | Authenticated user's Z-coin balance |
|
|
92
|
+
| `getMyHistory(input?)` | Query | Transaction history with pagination |
|
|
93
|
+
| `getDepositPackages(input?)` | Query | Available deposit packages with pricing |
|
|
94
|
+
| `createDepositOrder(input)` | Mutation | Create Stripe checkout for Z-coin deposit |
|
|
77
95
|
| `getDepositStatus(input)` | Query | Check deposit checkout session status |
|
|
78
|
-
| `commercialTransfer(input)` | Mutation | Atomic
|
|
79
|
-
| `mintAndCharge(input)` | Mutation |
|
|
80
|
-
| `chargeUser(input)` | Mutation | Charge
|
|
81
|
-
| `createDirectPurchaseOrder(input)` | Mutation |
|
|
96
|
+
| `commercialTransfer(input)` | Mutation | **Primary API for secondary market.** Atomic: debit buyer → credit seller → transfer ownership |
|
|
97
|
+
| `mintAndCharge(input)` | Mutation | **Primary API for primary sales.** Atomic: mint instance → charge buyer |
|
|
98
|
+
| `chargeUser(input)` | Mutation | Charge Z-coin for in-app purchases |
|
|
99
|
+
| `createDirectPurchaseOrder(input)` | Mutation | Fiat-to-Z-coin direct purchase checkout |
|
|
82
100
|
|
|
83
|
-
|
|
101
|
+
`commercialTransfer` is the most important method in the SDK. It atomically debits the buyer's Z-coin balance, credits the seller (minus platform fee), and transfers card instance ownership — all in a single database transaction. The `referenceId` parameter provides idempotency.
|
|
84
102
|
|
|
85
|
-
|
|
103
|
+
`mintAndCharge` is the primary API for primary sales (gacha, direct-from-creator). It mints a new card instance and charges the buyer in one atomic operation. Requires prior mint authorization via `inventory.grantMintAuth`.
|
|
86
104
|
|
|
87
|
-
|
|
105
|
+
### `goodz.inventory` — Card Instance Management
|
|
88
106
|
|
|
89
107
|
| Method | Type | Description |
|
|
90
108
|
|--------|------|-------------|
|
|
91
|
-
| `getUserInventory(input)` | Query |
|
|
109
|
+
| `getUserInventory(input)` | Query | User's owned card instances |
|
|
92
110
|
| `confirmOwnership(input)` | Query | Check if user owns a specific card |
|
|
93
|
-
| `mint(input)` | Mutation | Mint new
|
|
94
|
-
| `transfer(input)` | Mutation | Transfer
|
|
95
|
-
| `transferByCard(input)` | Mutation | Transfer
|
|
96
|
-
| `grantMintAuth(input)` | Mutation | Grant mint authorization to
|
|
97
|
-
| `transferHistory(input)` | Query |
|
|
111
|
+
| `mint(input)` | Mutation | Mint new instances (requires authorization) |
|
|
112
|
+
| `transfer(input)` | Mutation | Transfer instance by instanceId |
|
|
113
|
+
| `transferByCard(input)` | Mutation | Transfer by cardId (oldest first) |
|
|
114
|
+
| `grantMintAuth(input)` | Mutation | Grant mint authorization to app/user |
|
|
115
|
+
| `transferHistory(input)` | Query | Ownership/transfer history |
|
|
98
116
|
|
|
99
|
-
For commercial transactions
|
|
117
|
+
For commercial transactions, always use `zcoin.commercialTransfer` or `zcoin.mintAndCharge` instead of raw `transfer`/`mint`. The raw methods are for administrative operations and gift transfers only.
|
|
100
118
|
|
|
101
|
-
|
|
119
|
+
### `goodz.collectible` — Card & Instance Queries
|
|
102
120
|
|
|
103
121
|
| Method | Type | Description |
|
|
104
122
|
|--------|------|-------------|
|
|
105
|
-
| `getInstanceById(input)` | Query |
|
|
106
|
-
| `getPublicInstance(input)` | Query |
|
|
123
|
+
| `getInstanceById(input)` | Query | Instance by numeric ID |
|
|
124
|
+
| `getPublicInstance(input)` | Query | Instance by instance code |
|
|
107
125
|
| `getPublicInstancesBatch(input)` | Query | Batch-fetch instances (max 100) |
|
|
108
|
-
| `getCardProfile(input)` | Query |
|
|
109
|
-
| `getShellImageUrl(input)` | Query |
|
|
126
|
+
| `getCardProfile(input)` | Query | Card metadata, rarity, series info |
|
|
127
|
+
| `getShellImageUrl(input)` | Query | Shell (packaging) image URL |
|
|
110
128
|
|
|
111
|
-
|
|
129
|
+
### `goodz.ip` — IP Management (Franchise/Series/Card)
|
|
112
130
|
|
|
113
131
|
| Method | Type | Description |
|
|
114
132
|
|--------|------|-------------|
|
|
115
|
-
| `
|
|
116
|
-
| `
|
|
133
|
+
| `getFranchise(input)` | Query | Franchise by ID or slug |
|
|
134
|
+
| `getSeries(input)` | Query | Series by ID or slug |
|
|
135
|
+
| `listSeriesByFranchise(input)` | Query | All series in a franchise |
|
|
136
|
+
| `getCard(input)` | Query | Card by ID |
|
|
137
|
+
| `listCardsBySeries(input)` | Query | All cards in a series |
|
|
117
138
|
|
|
118
|
-
|
|
139
|
+
### `goodz.user` & `goodz.auth`
|
|
119
140
|
|
|
120
141
|
| Method | Type | Description |
|
|
121
142
|
|--------|------|-------------|
|
|
122
|
-
| `
|
|
123
|
-
| `
|
|
143
|
+
| `user.getPublicProfile(input)` | Query | Profile by openId |
|
|
144
|
+
| `user.getPublicProfileById(input)` | Query | Profile by userId |
|
|
145
|
+
| `auth.me()` | Query | Authenticated user's profile |
|
|
146
|
+
| `auth.getOAuthAppInfo(input)` | Query | OAuth app info by clientId |
|
|
147
|
+
|
|
148
|
+
## API Reference — Commerce Namespace
|
|
149
|
+
|
|
150
|
+
Commerce methods communicate via MCP JSON-RPC with `goodzcommerce.manus.space`. This namespace covers shop management, product assembly, campaigns, purchases, wholesale, and settlement.
|
|
151
|
+
|
|
152
|
+
### Shop & Product Assembly
|
|
153
|
+
|
|
154
|
+
| Method | Description |
|
|
155
|
+
|--------|-------------|
|
|
156
|
+
| `createShop(input)` | Create a new shop |
|
|
157
|
+
| `getShopDashboard()` | Shop dashboard with stats |
|
|
158
|
+
| `createBatch(input)` | Create a product batch (fixed-price bundle) |
|
|
159
|
+
| `createGachaPool(input)` | Create a gacha/blind-box pool with probability weights |
|
|
160
|
+
|
|
161
|
+
### Campaign Lifecycle
|
|
162
|
+
|
|
163
|
+
| Method | Description |
|
|
164
|
+
|--------|-------------|
|
|
165
|
+
| `launchCampaign(input)` | Launch a new sales campaign |
|
|
166
|
+
| `activateCampaign(input)` | Activate a paused campaign |
|
|
167
|
+
| `pauseCampaign(input)` | Pause an active campaign |
|
|
168
|
+
| `endCampaign(input)` | End a campaign permanently |
|
|
169
|
+
| `updateCampaign(input)` | Update campaign details |
|
|
170
|
+
| `getCampaignInfo(input)` | Get campaign info |
|
|
171
|
+
| `getCampaignItems(input)` | Get items in a campaign |
|
|
172
|
+
|
|
173
|
+
### Purchase & Orders
|
|
174
|
+
|
|
175
|
+
| Method | Description |
|
|
176
|
+
|--------|-------------|
|
|
177
|
+
| `executePurchase(input)` | Execute a purchase (direct or gacha draw) |
|
|
178
|
+
| `getMyOrders()` | User's order history |
|
|
179
|
+
|
|
180
|
+
### Wholesale
|
|
181
|
+
|
|
182
|
+
| Method | Description |
|
|
183
|
+
|--------|-------------|
|
|
184
|
+
| `publishToWholesale(input)` | Publish batch to wholesale market |
|
|
185
|
+
| `browseWholesale()` | Browse wholesale listings |
|
|
186
|
+
| `procureBatch(input)` | Procure a wholesale batch for resale |
|
|
187
|
+
|
|
188
|
+
### Inventory & Fulfillment
|
|
189
|
+
|
|
190
|
+
| Method | Description |
|
|
191
|
+
|--------|-------------|
|
|
192
|
+
| `manageInventory(input)` | View/manage shop inventory |
|
|
193
|
+
| `registerInstances(input)` | Register minted instances to shop |
|
|
194
|
+
| `mintToInventory(input)` | Mint + register in one step |
|
|
195
|
+
| `redeemPhysical(input)` | Redeem a physical item |
|
|
196
|
+
|
|
197
|
+
### Settlement & Discovery
|
|
198
|
+
|
|
199
|
+
| Method | Description |
|
|
200
|
+
|--------|-------------|
|
|
201
|
+
| `getSettlementReport()` | Revenue and settlement report |
|
|
202
|
+
| `searchMarketplace(input)` | Search across all shops |
|
|
203
|
+
| `getShopsByBlueprint(input)` | Find shops selling a specific card |
|
|
204
|
+
|
|
205
|
+
### Webhooks & App Management
|
|
206
|
+
|
|
207
|
+
| Method | Description |
|
|
208
|
+
|--------|-------------|
|
|
209
|
+
| `registerWebhook(input)` | Register event webhook |
|
|
210
|
+
| `listWebhooks()` | List registered webhooks |
|
|
211
|
+
| `testWebhook(input)` | Test a webhook endpoint |
|
|
212
|
+
| `deleteWebhook(input)` | Delete a webhook |
|
|
213
|
+
| `registerApp(input)` | Register an app on Commerce |
|
|
214
|
+
| `updateApp(input)` | Update app details |
|
|
215
|
+
| `listMyApps()` | List your registered apps |
|
|
216
|
+
| `getAuthUrl()` | Get Commerce OAuth URL |
|
|
217
|
+
|
|
218
|
+
### Commerce Escape Hatch
|
|
124
219
|
|
|
125
|
-
|
|
220
|
+
```ts
|
|
221
|
+
// For MCP tools not yet in the typed API
|
|
222
|
+
const result = await goodz.commerce.rawTool("some_new_tool", { key: "value" });
|
|
223
|
+
```
|
|
126
224
|
|
|
127
|
-
|
|
128
|
-
|--------|------|-------------|
|
|
129
|
-
| `getFranchise(input)` | Query | Get franchise by ID or slug |
|
|
130
|
-
| `getSeries(input)` | Query | Get series by ID or slug |
|
|
131
|
-
| `listSeriesByFranchise(input)` | Query | List all series in a franchise |
|
|
132
|
-
| `getCard(input)` | Query | Get card by ID |
|
|
133
|
-
| `listCardsBySeries(input)` | Query | List all cards in a series |
|
|
225
|
+
## API Reference — Exchange Namespace
|
|
134
226
|
|
|
135
|
-
|
|
227
|
+
Exchange methods communicate via MCP JSON-RPC with `goodzexchange.manus.space`. This namespace covers the secondary market: listings, auctions, want-to-buy requests, P2P trades, and market data.
|
|
136
228
|
|
|
137
|
-
|
|
229
|
+
### Marketplace & Listings
|
|
230
|
+
|
|
231
|
+
| Method | Description |
|
|
232
|
+
|--------|-------------|
|
|
233
|
+
| `browseMarketplace(input?)` | Browse active listings with filters |
|
|
234
|
+
| `getListingDetail(input)` | Get listing details |
|
|
235
|
+
| `createListing(input)` | Create listing (fixed_price or auction). Core locks the instance |
|
|
236
|
+
| `cancelListing(input)` | Cancel listing. Core unlocks the instance |
|
|
237
|
+
|
|
238
|
+
### Purchase & Bidding
|
|
239
|
+
|
|
240
|
+
| Method | Description |
|
|
241
|
+
|--------|-------------|
|
|
242
|
+
| `buyListing(input)` | Buy a fixed-price listing. Z-coin debit + ownership transfer |
|
|
243
|
+
| `placeBid(input)` | Bid on auction. If meets buy-now price → instant purchase |
|
|
244
|
+
| `getBids(input)` | All bids for an auction (highest first) |
|
|
245
|
+
|
|
246
|
+
### Want-to-Buy (WTB)
|
|
247
|
+
|
|
248
|
+
| Method | Description |
|
|
249
|
+
|--------|-------------|
|
|
250
|
+
| `createWtb(input)` | Post a want-to-buy request |
|
|
251
|
+
| `fulfillWtb(input)` | Fulfill a WTB by offering your item |
|
|
252
|
+
| `cancelWtb(input)` | Cancel your WTB request |
|
|
253
|
+
|
|
254
|
+
### P2P Trade
|
|
255
|
+
|
|
256
|
+
| Method | Description |
|
|
257
|
+
|--------|-------------|
|
|
258
|
+
| `proposeTrade(input)` | Propose an item swap (optional Z-coin compensation) |
|
|
259
|
+
| `respondToTrade(input)` | Accept/reject trade. If accepted → all items transfer atomically |
|
|
260
|
+
|
|
261
|
+
### Watchlist & Market Data
|
|
262
|
+
|
|
263
|
+
| Method | Description |
|
|
264
|
+
|--------|-------------|
|
|
265
|
+
| `getWatchlist()` | Your watchlist |
|
|
266
|
+
| `addToWatchlist(input)` | Add to watchlist |
|
|
267
|
+
| `removeFromWatchlist(input)` | Remove from watchlist |
|
|
268
|
+
| `getMarketData(input)` | Price history, floor price, volume, trends |
|
|
269
|
+
|
|
270
|
+
### Exchange Escape Hatch
|
|
138
271
|
|
|
139
272
|
```ts
|
|
140
|
-
const
|
|
141
|
-
const result = await goodz.rawMutation("some.newMutation", { name: "test" });
|
|
273
|
+
const result = await goodz.exchange.rawTool("some_new_tool", { key: "value" });
|
|
142
274
|
```
|
|
143
275
|
|
|
144
|
-
##
|
|
276
|
+
## API Reference — Alive Namespace
|
|
145
277
|
|
|
146
|
-
|
|
278
|
+
Alive methods communicate via MCP JSON-RPC with `goodzalive.manus.space`. This namespace powers AI companion interactions: memory, intimacy, context building, and conversation.
|
|
147
279
|
|
|
148
|
-
|
|
280
|
+
| Method | Description |
|
|
281
|
+
|--------|-------------|
|
|
282
|
+
| `storeMemory(input)` | Store a memory for a character-user pair |
|
|
283
|
+
| `recallMemories(input)` | Semantic search for relevant memories |
|
|
284
|
+
| `forgetMemory(input)` | Delete a specific memory |
|
|
285
|
+
| `getIntimacy(input)` | Get intimacy/affection state between character and user |
|
|
286
|
+
| `updateIntimacy(input)` | Update intimacy level after interaction |
|
|
287
|
+
| `buildContext(input)` | Build full AI context (profile + memories + history + system prompt) |
|
|
288
|
+
| `classifyIntent(input)` | Classify user message into intent category |
|
|
289
|
+
| `sendMessage(input)` | Send message → get character response (includes memory/intimacy processing) |
|
|
290
|
+
|
|
291
|
+
### Alive Escape Hatch
|
|
292
|
+
|
|
293
|
+
```ts
|
|
294
|
+
const result = await goodz.alive.rawTool("some_new_tool", { key: "value" });
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
## Authentication
|
|
298
|
+
|
|
299
|
+
### Static Token (simplest)
|
|
149
300
|
|
|
150
301
|
```ts
|
|
151
302
|
const goodz = createGoodZClient({
|
|
@@ -169,7 +320,6 @@ const tokenManager = new TokenManager({
|
|
|
169
320
|
expiresAt: savedExpiresAt,
|
|
170
321
|
},
|
|
171
322
|
onTokenRefresh: async (tokens) => {
|
|
172
|
-
// Persist refreshed tokens to your database
|
|
173
323
|
await db.update(appTokens).set({
|
|
174
324
|
accessToken: tokens.accessToken,
|
|
175
325
|
refreshToken: tokens.refreshToken,
|
|
@@ -198,7 +348,7 @@ const authUrl = buildAuthorizationUrl({
|
|
|
198
348
|
state: crypto.randomUUID(),
|
|
199
349
|
});
|
|
200
350
|
|
|
201
|
-
// Step 2: Exchange code for tokens
|
|
351
|
+
// Step 2: Exchange code for tokens
|
|
202
352
|
const tokens = await exchangeCode({
|
|
203
353
|
clientId: "od_myapp",
|
|
204
354
|
clientSecret: process.env.CLIENT_SECRET,
|
|
@@ -214,7 +364,7 @@ const userGoodz = createGoodZClient({
|
|
|
214
364
|
|
|
215
365
|
## Z-coin Precision
|
|
216
366
|
|
|
217
|
-
GoodZ
|
|
367
|
+
GoodZ stores Z-coin amounts in **hundredths** (1/100th of a Z-coin). For example, 10.50 Z-coin is stored as `1050`.
|
|
218
368
|
|
|
219
369
|
```ts
|
|
220
370
|
import { toHundredths, toDisplay, formatZcoin } from "@goodz-core/sdk/zcoin";
|
|
@@ -224,7 +374,7 @@ toDisplay(1050); // → 10.5
|
|
|
224
374
|
formatZcoin(1050); // → "10.50"
|
|
225
375
|
```
|
|
226
376
|
|
|
227
|
-
Always use `toHundredths()` when constructing API inputs
|
|
377
|
+
Always use `toHundredths()` when constructing API inputs:
|
|
228
378
|
|
|
229
379
|
```ts
|
|
230
380
|
// ✅ Correct
|
|
@@ -242,7 +392,7 @@ await goodz.zcoin.commercialTransfer({
|
|
|
242
392
|
|
|
243
393
|
## Error Handling
|
|
244
394
|
|
|
245
|
-
All API errors are thrown as `GoodZApiError` instances
|
|
395
|
+
All API errors are thrown as `GoodZApiError` instances:
|
|
246
396
|
|
|
247
397
|
```ts
|
|
248
398
|
import { GoodZApiError } from "@goodz-core/sdk";
|
|
@@ -251,33 +401,67 @@ try {
|
|
|
251
401
|
await goodz.zcoin.commercialTransfer({ /* ... */ });
|
|
252
402
|
} catch (err) {
|
|
253
403
|
if (err instanceof GoodZApiError) {
|
|
254
|
-
console.error(err.code); // "BAD_REQUEST", "FORBIDDEN",
|
|
255
|
-
console.error(err.httpStatus); // 400, 403,
|
|
404
|
+
console.error(err.code); // "BAD_REQUEST", "FORBIDDEN", etc.
|
|
405
|
+
console.error(err.httpStatus); // 400, 403, etc.
|
|
256
406
|
console.error(err.path); // "zcoin.commercialTransfer"
|
|
257
|
-
console.error(err.message); // Human-readable
|
|
258
|
-
|
|
259
|
-
// Zod validation errors (if input was malformed)
|
|
407
|
+
console.error(err.message); // Human-readable message
|
|
260
408
|
if (err.zodErrors) {
|
|
261
409
|
for (const fieldErr of err.zodErrors) {
|
|
262
410
|
console.error(`${fieldErr.path.join(".")}: ${fieldErr.message}`);
|
|
263
411
|
}
|
|
264
412
|
}
|
|
265
|
-
|
|
266
|
-
// Full detailed string for logging
|
|
267
|
-
console.error(err.toDetailedString());
|
|
268
413
|
}
|
|
269
414
|
}
|
|
270
415
|
```
|
|
271
416
|
|
|
272
|
-
|
|
417
|
+
| Code | HTTP | Meaning | Action |
|
|
418
|
+
|------|------|---------|--------|
|
|
419
|
+
| `BAD_REQUEST` | 400 | Invalid input or insufficient balance | Check input values |
|
|
420
|
+
| `UNAUTHORIZED` | 401 | Missing or invalid token | Refresh token or re-login |
|
|
421
|
+
| `FORBIDDEN` | 403 | No permission | Show permission denied |
|
|
422
|
+
| `NOT_FOUND` | 404 | Resource doesn't exist | Show 404 or fallback |
|
|
423
|
+
| `CONFLICT` | 409 | Version conflict | Retry the operation |
|
|
424
|
+
|
|
425
|
+
## UI Components (React)
|
|
426
|
+
|
|
427
|
+
The SDK includes a React component for displaying GoodZ collectibles with full material effects and tilt interaction — the same experience used on GoodZ.Core itself.
|
|
428
|
+
|
|
429
|
+
### GoodZCardFocus
|
|
430
|
+
|
|
431
|
+
```tsx
|
|
432
|
+
import { GoodZCardFocus } from "@goodz-core/sdk/ui";
|
|
433
|
+
|
|
434
|
+
<GoodZCardFocus
|
|
435
|
+
imageUrl="https://goodzcore.manus.space/api/shell/42.png"
|
|
436
|
+
cardName="Luna"
|
|
437
|
+
rarity="SSR"
|
|
438
|
+
formFactor="trading_card"
|
|
439
|
+
>
|
|
440
|
+
<img src={thumbnailUrl} alt="Luna" className="w-full rounded-lg" />
|
|
441
|
+
</GoodZCardFocus>
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
Supports all 10 form factors with unique material effects:
|
|
445
|
+
|
|
446
|
+
| Form Factor | Material Effect |
|
|
447
|
+
|---|---|
|
|
448
|
+
| `trading_card` | Holographic gradient + sparkle (intensity by rarity) |
|
|
449
|
+
| `postcard` / `postcard_portrait` | Paper texture + subtle shadow |
|
|
450
|
+
| `polaroid` | White border (thick bottom) + paper texture |
|
|
451
|
+
| `laser_ticket` | Intense rainbow holographic + shimmer animation |
|
|
452
|
+
| `badge_*` | Circular clip + metal frame + dome highlight |
|
|
453
|
+
| `acrylic_stand_*` | Transparent glass + edge refraction + caustic |
|
|
273
454
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
455
|
+
Interaction: desktop mouse tilt, mobile gyroscope (auto-detected), touch drag fallback, iOS permission prompt. React 18+ peer dependency. No CSS framework required.
|
|
456
|
+
|
|
457
|
+
### Form Factor Utilities
|
|
458
|
+
|
|
459
|
+
```ts
|
|
460
|
+
import { FORM_FACTORS, getAspectRatioCSS, getFormFactorSpec } from "@goodz-core/sdk/ui";
|
|
461
|
+
|
|
462
|
+
getAspectRatioCSS("trading_card"); // "5 / 7"
|
|
463
|
+
getFormFactorSpec("polaroid"); // { key, label, aspectRatio: [3, 4], isCircle: false }
|
|
464
|
+
```
|
|
281
465
|
|
|
282
466
|
## Subpath Imports
|
|
283
467
|
|
|
@@ -287,6 +471,10 @@ For tree-shaking, import from specific subpaths:
|
|
|
287
471
|
import { createGoodZClient } from "@goodz-core/sdk/core";
|
|
288
472
|
import { TokenManager } from "@goodz-core/sdk/auth";
|
|
289
473
|
import { toHundredths } from "@goodz-core/sdk/zcoin";
|
|
474
|
+
import { GoodZCardFocus } from "@goodz-core/sdk/ui";
|
|
475
|
+
import { createCommerceNamespace } from "@goodz-core/sdk/commerce";
|
|
476
|
+
import { createExchangeNamespace } from "@goodz-core/sdk/exchange";
|
|
477
|
+
import { createAliveNamespace } from "@goodz-core/sdk/alive";
|
|
290
478
|
```
|
|
291
479
|
|
|
292
480
|
The root import (`@goodz-core/sdk`) re-exports everything for convenience.
|