@echoxyz/sonar-react 0.4.2 → 0.5.0

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @echoxyz/sonar-react
2
2
 
3
+ ## 0.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 2e6e793: Introduce useSonarPurchase hook
8
+
3
9
  ## 0.4.2
4
10
 
5
11
  ### Patch Changes
package/README.md CHANGED
@@ -118,52 +118,76 @@ const ExampleEntityPanel = () => {
118
118
 
119
119
  ```
120
120
 
121
- 5. Optional: call APIs with the low level client to implement the purchase flow:
121
+ 5. Implement the purchase flow
122
122
 
123
123
  ```tsx
124
- import { useEffect } from "react";
125
- import { useSonarEntity } from "./hooks/useSonarEntity";
126
- import { useAccount } from "wagmi";
127
-
128
- export function Example() {
129
- const { address, isConnected } = useAccount();
130
- // Would normally need to handle loading and error states like above
131
- const { entity } = useSonarEntity({
132
- saleUUID: "<your-sale-uuid>",
133
- wallet: { address, isConnected },
134
- });
135
- const client = useSonarClient();
136
-
137
- useEffect(() => {
138
- if (!entity) {
139
- return;
140
- }
124
+ function Example({
125
+ entityUUID,
126
+ walletAddress,
127
+ }: {
128
+ entityUUID: string;
129
+ walletAddress: string;
130
+ }) {
131
+ const sonarPurchaser = useSonarPurchase({
132
+ saleUUID: sonarConfig.saleUUID,
133
+ entityUUID,
134
+ entityType,
135
+ walletAddress,
136
+ });
137
+
138
+ if (sonarPurchaser.loading) {
139
+ return <p>Loading...</p>;
140
+ }
141
+
142
+ if (sonarPurchaser.error) {
143
+ return <p>Error: {error.message}</p>;
144
+ }
145
+
146
+ return (
147
+ <div>
148
+ {sonarPurchaser.readyToPurchase && (
149
+ <PurchaseButton
150
+ generatePurchasePermit={sonarPurchaser.generatePurchasePermit}
151
+ />
152
+ )}
153
+
154
+ {!sonarPurchaser.readyToPurchase &&
155
+ sonarPurchaser.failureReason ===
156
+ PrePurchaseFailureReason.REQUIRES_LIVENESS && (
157
+ <button
158
+ onClick={() => {
159
+ window.open(prePurchaseCheckResult.LivenessCheckURL, "_blank");
160
+ }}
161
+ >
162
+ Complete liveness check to purchase
163
+ </button>
164
+ )}
165
+ </div>
166
+ );
167
+ }
141
168
 
142
- (async () => {
143
- const pre = await client.prePurchaseCheck({
144
- saleUUID: "<your-sale-uuid>",
145
- entityUUID: entity.EntityUUID,
146
- walletAddress: "0x1234...abcd" as `0x${string}`,
147
- });
148
-
149
- if (pre.ReadyToPurchase) {
150
- const permit = await client.generatePurchasePermit({
151
- saleUUID: "<your-sale-uuid>",
152
- entityUUID: entity.EntityUUID,
153
- walletAddress: "0x1234...abcd" as `0x${string}`,
154
- });
155
- console.log(permit.Signature, permit.Permit);
156
- }
157
-
158
- const alloc = await client.fetchAllocation({
159
- saleUUID: "<your-sale-uuid>",
160
- walletAddress,
161
- });
162
- console.log(alloc);
163
- })();
164
- }, [entity]);
169
+ function PurchaseButton({
170
+ generatePurchasePermit,
171
+ }: {
172
+ generatePurchasePermit: () => Promise<GeneratePurchasePermitResponse>;
173
+ }) {
174
+ const purchase = async () => {
175
+ const response = await generatePurchasePermit();
176
+ const r = response as unknown as {
177
+ Signature: string;
178
+ PermitJSON: AllocationPermit;
179
+ };
180
+ if (r.Signature && r.PermitJSON) {
181
+ console.log(permit.Signature, permit.Permit);
182
+ return;
183
+ }
184
+ };
165
185
 
166
- return null;
186
+ return (
187
+ <button onClick={purchase}>
188
+ Purchase
189
+ </button>
190
+ );
167
191
  }
168
192
  ```
169
193
 
package/dist/index.cjs CHANGED
@@ -23,7 +23,8 @@ __export(index_exports, {
23
23
  SonarProvider: () => SonarProvider,
24
24
  useSonarAuth: () => useSonarAuth,
25
25
  useSonarClient: () => useSonarClient,
26
- useSonarEntity: () => useSonarEntity
26
+ useSonarEntity: () => useSonarEntity,
27
+ useSonarPurchase: () => useSonarPurchase
27
28
  });
28
29
  module.exports = __toCommonJS(index_exports);
29
30
 
@@ -192,10 +193,70 @@ function useSonarEntity(args) {
192
193
  error: state.error
193
194
  };
194
195
  }
196
+ function useSonarPurchase(args) {
197
+ const saleUUID = args.saleUUID;
198
+ const entityUUID = args.entityUUID;
199
+ const walletAddress = args.walletAddress;
200
+ const client = useSonarClient();
201
+ const [state, setState] = (0, import_react2.useState)({
202
+ loading: true,
203
+ readyToPurchase: false,
204
+ error: void 0
205
+ });
206
+ const generatePurchasePermit = (0, import_react2.useCallback)(() => {
207
+ return client.generatePurchasePermit({
208
+ saleUUID,
209
+ entityUUID,
210
+ walletAddress
211
+ });
212
+ }, [client, saleUUID, entityUUID, walletAddress]);
213
+ (0, import_react2.useEffect)(() => {
214
+ const fetchPurchaseData = async () => {
215
+ setState({
216
+ loading: true,
217
+ readyToPurchase: false,
218
+ error: void 0
219
+ });
220
+ try {
221
+ const response = await client.prePurchaseCheck({
222
+ saleUUID,
223
+ entityUUID,
224
+ walletAddress
225
+ });
226
+ if (response.ReadyToPurchase) {
227
+ setState({
228
+ loading: false,
229
+ readyToPurchase: true,
230
+ generatePurchasePermit,
231
+ error: void 0
232
+ });
233
+ } else {
234
+ setState({
235
+ loading: false,
236
+ readyToPurchase: false,
237
+ failureReason: response.FailureReason,
238
+ livenessCheckURL: response.LivenessCheckURL,
239
+ error: void 0
240
+ });
241
+ }
242
+ } catch (err) {
243
+ const error = err instanceof Error ? err : new Error(String(err));
244
+ setState({
245
+ loading: false,
246
+ readyToPurchase: false,
247
+ error
248
+ });
249
+ }
250
+ };
251
+ fetchPurchaseData();
252
+ }, [saleUUID, entityUUID, walletAddress, client, generatePurchasePermit]);
253
+ return state;
254
+ }
195
255
  // Annotate the CommonJS export names for ESM import in node:
196
256
  0 && (module.exports = {
197
257
  SonarProvider,
198
258
  useSonarAuth,
199
259
  useSonarClient,
200
- useSonarEntity
260
+ useSonarEntity,
261
+ useSonarPurchase
201
262
  });
package/dist/index.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import React from 'react';
3
- import { SonarClient, EntityDetails } from '@echoxyz/sonar-core';
3
+ import { SonarClient, EntityDetails, GeneratePurchasePermitResponse, PrePurchaseFailureReason } from '@echoxyz/sonar-core';
4
4
 
5
5
  type SonarProviderProps = {
6
6
  children: React.ReactNode;
@@ -39,5 +39,34 @@ declare function useSonarEntity(args: {
39
39
  saleUUID: string;
40
40
  walletAddress?: string;
41
41
  }): UseSonarEntityResult;
42
+ type UseSonarPurchaseResultReadyToPurchase = {
43
+ loading: false;
44
+ readyToPurchase: true;
45
+ error: undefined;
46
+ generatePurchasePermit: () => Promise<GeneratePurchasePermitResponse>;
47
+ };
48
+ type UseSonarPurchaseResultNotReadyToPurchase = {
49
+ loading: false;
50
+ readyToPurchase: false;
51
+ error: undefined;
52
+ failureReason: PrePurchaseFailureReason;
53
+ livenessCheckURL: string;
54
+ };
55
+ type UseSonarPurchaseResultError = {
56
+ loading: false;
57
+ readyToPurchase: false;
58
+ error: Error;
59
+ };
60
+ type UseSonarPurchaseResultLoading = {
61
+ loading: true;
62
+ readyToPurchase: false;
63
+ error: undefined;
64
+ };
65
+ type UseSonarPurchaseResult = UseSonarPurchaseResultLoading | UseSonarPurchaseResultReadyToPurchase | UseSonarPurchaseResultNotReadyToPurchase | UseSonarPurchaseResultError;
66
+ declare function useSonarPurchase(args: {
67
+ saleUUID: string;
68
+ entityUUID: string;
69
+ walletAddress: string;
70
+ }): UseSonarPurchaseResult;
42
71
 
43
- export { SonarProvider, type SonarProviderConfig, type UseSonarEntityResult, useSonarAuth, useSonarClient, useSonarEntity };
72
+ export { SonarProvider, type SonarProviderConfig, type UseSonarEntityResult, type UseSonarPurchaseResult, type UseSonarPurchaseResultError, type UseSonarPurchaseResultLoading, type UseSonarPurchaseResultNotReadyToPurchase, type UseSonarPurchaseResultReadyToPurchase, useSonarAuth, useSonarClient, useSonarEntity, useSonarPurchase };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import React from 'react';
3
- import { SonarClient, EntityDetails } from '@echoxyz/sonar-core';
3
+ import { SonarClient, EntityDetails, GeneratePurchasePermitResponse, PrePurchaseFailureReason } from '@echoxyz/sonar-core';
4
4
 
5
5
  type SonarProviderProps = {
6
6
  children: React.ReactNode;
@@ -39,5 +39,34 @@ declare function useSonarEntity(args: {
39
39
  saleUUID: string;
40
40
  walletAddress?: string;
41
41
  }): UseSonarEntityResult;
42
+ type UseSonarPurchaseResultReadyToPurchase = {
43
+ loading: false;
44
+ readyToPurchase: true;
45
+ error: undefined;
46
+ generatePurchasePermit: () => Promise<GeneratePurchasePermitResponse>;
47
+ };
48
+ type UseSonarPurchaseResultNotReadyToPurchase = {
49
+ loading: false;
50
+ readyToPurchase: false;
51
+ error: undefined;
52
+ failureReason: PrePurchaseFailureReason;
53
+ livenessCheckURL: string;
54
+ };
55
+ type UseSonarPurchaseResultError = {
56
+ loading: false;
57
+ readyToPurchase: false;
58
+ error: Error;
59
+ };
60
+ type UseSonarPurchaseResultLoading = {
61
+ loading: true;
62
+ readyToPurchase: false;
63
+ error: undefined;
64
+ };
65
+ type UseSonarPurchaseResult = UseSonarPurchaseResultLoading | UseSonarPurchaseResultReadyToPurchase | UseSonarPurchaseResultNotReadyToPurchase | UseSonarPurchaseResultError;
66
+ declare function useSonarPurchase(args: {
67
+ saleUUID: string;
68
+ entityUUID: string;
69
+ walletAddress: string;
70
+ }): UseSonarPurchaseResult;
42
71
 
43
- export { SonarProvider, type SonarProviderConfig, type UseSonarEntityResult, useSonarAuth, useSonarClient, useSonarEntity };
72
+ export { SonarProvider, type SonarProviderConfig, type UseSonarEntityResult, type UseSonarPurchaseResult, type UseSonarPurchaseResultError, type UseSonarPurchaseResultLoading, type UseSonarPurchaseResultNotReadyToPurchase, type UseSonarPurchaseResultReadyToPurchase, useSonarAuth, useSonarClient, useSonarEntity, useSonarPurchase };
package/dist/index.js CHANGED
@@ -76,17 +76,19 @@ function SonarProvider({ children, config }) {
76
76
  }
77
77
 
78
78
  // src/hooks.ts
79
- import { APIError } from "@echoxyz/sonar-core";
80
- import { useCallback as useCallback2, useContext as useContext2, useEffect as useEffect2, useState as useState2 } from "react";
79
+ import {
80
+ APIError
81
+ } from "@echoxyz/sonar-core";
82
+ import { useCallback as useCallback2, useContext, useEffect as useEffect2, useState as useState2 } from "react";
81
83
  function useSonarAuth() {
82
- const ctx = useContext2(AuthContext);
84
+ const ctx = useContext(AuthContext);
83
85
  if (!ctx) {
84
86
  throw new Error("useSonarAuth must be used within a SonarProvider");
85
87
  }
86
88
  return ctx;
87
89
  }
88
90
  function useSonarClient() {
89
- const ctx = useContext2(ClientContext);
91
+ const ctx = useContext(ClientContext);
90
92
  if (!ctx) {
91
93
  throw new Error("useSonarClient must be used within a SonarProvider");
92
94
  }
@@ -163,9 +165,69 @@ function useSonarEntity(args) {
163
165
  error: state.error
164
166
  };
165
167
  }
168
+ function useSonarPurchase(args) {
169
+ const saleUUID = args.saleUUID;
170
+ const entityUUID = args.entityUUID;
171
+ const walletAddress = args.walletAddress;
172
+ const client = useSonarClient();
173
+ const [state, setState] = useState2({
174
+ loading: true,
175
+ readyToPurchase: false,
176
+ error: void 0
177
+ });
178
+ const generatePurchasePermit = useCallback2(() => {
179
+ return client.generatePurchasePermit({
180
+ saleUUID,
181
+ entityUUID,
182
+ walletAddress
183
+ });
184
+ }, [client, saleUUID, entityUUID, walletAddress]);
185
+ useEffect2(() => {
186
+ const fetchPurchaseData = async () => {
187
+ setState({
188
+ loading: true,
189
+ readyToPurchase: false,
190
+ error: void 0
191
+ });
192
+ try {
193
+ const response = await client.prePurchaseCheck({
194
+ saleUUID,
195
+ entityUUID,
196
+ walletAddress
197
+ });
198
+ if (response.ReadyToPurchase) {
199
+ setState({
200
+ loading: false,
201
+ readyToPurchase: true,
202
+ generatePurchasePermit,
203
+ error: void 0
204
+ });
205
+ } else {
206
+ setState({
207
+ loading: false,
208
+ readyToPurchase: false,
209
+ failureReason: response.FailureReason,
210
+ livenessCheckURL: response.LivenessCheckURL,
211
+ error: void 0
212
+ });
213
+ }
214
+ } catch (err) {
215
+ const error = err instanceof Error ? err : new Error(String(err));
216
+ setState({
217
+ loading: false,
218
+ readyToPurchase: false,
219
+ error
220
+ });
221
+ }
222
+ };
223
+ fetchPurchaseData();
224
+ }, [saleUUID, entityUUID, walletAddress, client, generatePurchasePermit]);
225
+ return state;
226
+ }
166
227
  export {
167
228
  SonarProvider,
168
229
  useSonarAuth,
169
230
  useSonarClient,
170
- useSonarEntity
231
+ useSonarEntity,
232
+ useSonarPurchase
171
233
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@echoxyz/sonar-react",
3
- "version": "0.4.2",
3
+ "version": "0.5.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",