@liberfi.io/react-redpacket 0.1.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 +12 -0
- package/dist/index.d.mts +107 -0
- package/dist/index.d.ts +107 -0
- package/dist/index.js +147 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +138 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +60 -0
package/README.md
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# @liberfi.io/react-redpacket
|
|
2
|
+
|
|
3
|
+
Redpacket domain runtime and React bindings.
|
|
4
|
+
|
|
5
|
+
This package is wallet-agnostic. ChainStream, Pinata, Privy, Next, and
|
|
6
|
+
browser routes stay in the application Adapter.
|
|
7
|
+
|
|
8
|
+
## Installation
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
pnpm add @liberfi.io/react-redpacket
|
|
12
|
+
```
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { PropsWithChildren } from 'react';
|
|
3
|
+
import { Chain } from '@liberfi.io/types';
|
|
4
|
+
|
|
5
|
+
declare const redPacketQueryKeys: {
|
|
6
|
+
packet: (idOrShareId: string) => readonly ["redPacket", string];
|
|
7
|
+
walletClaims: (address: string, cursor?: string) => readonly ["walletClaims", string, string];
|
|
8
|
+
packetClaims: (redPacketId: string, cursor?: string) => readonly ["redPacketClaims", string, string];
|
|
9
|
+
walletPackets: (address: string, cursor?: string) => readonly ["walletRedPackets", string, string];
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
interface CreateFixedAmountRedPacketIntent {
|
|
13
|
+
chain: Chain;
|
|
14
|
+
creator: string;
|
|
15
|
+
mint: string;
|
|
16
|
+
maxClaims: number;
|
|
17
|
+
fixedAmount: string;
|
|
18
|
+
memo?: string;
|
|
19
|
+
password?: string;
|
|
20
|
+
}
|
|
21
|
+
interface CreateRandomAmountRedPacketIntent {
|
|
22
|
+
chain: Chain;
|
|
23
|
+
creator: string;
|
|
24
|
+
mint: string;
|
|
25
|
+
maxClaims: number;
|
|
26
|
+
totalAmount: string;
|
|
27
|
+
memo?: string;
|
|
28
|
+
password?: string;
|
|
29
|
+
}
|
|
30
|
+
interface ClaimRedPacketIntent {
|
|
31
|
+
chain: Chain;
|
|
32
|
+
shareId: string;
|
|
33
|
+
claimer: string;
|
|
34
|
+
password?: string;
|
|
35
|
+
}
|
|
36
|
+
type RedpacketPacketStatus = "ongoing" | "finished" | "expired";
|
|
37
|
+
interface RedpacketRecord {
|
|
38
|
+
id: string;
|
|
39
|
+
shareId: string;
|
|
40
|
+
status: RedpacketPacketStatus;
|
|
41
|
+
totalAmount: string;
|
|
42
|
+
claimedAmount?: string;
|
|
43
|
+
claimedCount?: number;
|
|
44
|
+
maxClaims: number;
|
|
45
|
+
memo?: string;
|
|
46
|
+
mint?: string;
|
|
47
|
+
creator?: string;
|
|
48
|
+
expiredAt?: number;
|
|
49
|
+
}
|
|
50
|
+
declare function redpacketRecordStatus(record: Pick<RedpacketRecord, "claimedAmount" | "totalAmount" | "claimedCount" | "maxClaims" | "expiredAt">): RedpacketPacketStatus;
|
|
51
|
+
type RedpacketIntentStatus = "idle" | "validating" | "signing" | "submitting" | "succeeded" | "failed" | "rejected" | "already-claimed";
|
|
52
|
+
|
|
53
|
+
type RedpacketCommand = {
|
|
54
|
+
kind: "create-fixed";
|
|
55
|
+
intent: CreateFixedAmountRedPacketIntent;
|
|
56
|
+
} | {
|
|
57
|
+
kind: "create-random";
|
|
58
|
+
intent: CreateRandomAmountRedPacketIntent;
|
|
59
|
+
} | {
|
|
60
|
+
kind: "claim";
|
|
61
|
+
intent: ClaimRedPacketIntent;
|
|
62
|
+
};
|
|
63
|
+
interface RedpacketSnapshot {
|
|
64
|
+
status: RedpacketIntentStatus;
|
|
65
|
+
command?: RedpacketCommand;
|
|
66
|
+
packetId?: string;
|
|
67
|
+
error?: Error;
|
|
68
|
+
}
|
|
69
|
+
interface RedpacketSignerPort {
|
|
70
|
+
sign(command: RedpacketCommand): Promise<string>;
|
|
71
|
+
}
|
|
72
|
+
interface RedpacketExecutionPort {
|
|
73
|
+
submit(signed: string, command: RedpacketCommand): Promise<{
|
|
74
|
+
packetId: string;
|
|
75
|
+
alreadyClaimed?: boolean;
|
|
76
|
+
}>;
|
|
77
|
+
}
|
|
78
|
+
declare function validateRedpacketCommand(command: RedpacketCommand): void;
|
|
79
|
+
declare function createRedpacketRuntime(options: {
|
|
80
|
+
signer?: RedpacketSignerPort;
|
|
81
|
+
execution: RedpacketExecutionPort;
|
|
82
|
+
onChange?: (snapshot: RedpacketSnapshot) => void;
|
|
83
|
+
}): {
|
|
84
|
+
snapshot(): RedpacketSnapshot;
|
|
85
|
+
submit(command: RedpacketCommand): Promise<RedpacketSnapshot>;
|
|
86
|
+
};
|
|
87
|
+
declare function createInMemoryRedpacketPorts(options?: {
|
|
88
|
+
signError?: Error;
|
|
89
|
+
alreadyClaimed?: boolean;
|
|
90
|
+
timeout?: boolean;
|
|
91
|
+
}): {
|
|
92
|
+
signer: {
|
|
93
|
+
sign(): Promise<string>;
|
|
94
|
+
};
|
|
95
|
+
execution: {
|
|
96
|
+
submit(signed: string, command: RedpacketCommand): Promise<{
|
|
97
|
+
packetId: string;
|
|
98
|
+
alreadyClaimed: boolean | undefined;
|
|
99
|
+
}>;
|
|
100
|
+
};
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
declare const PACKAGE_NAME: "@liberfi.io/react-redpacket";
|
|
104
|
+
declare function RedpacketProvider({ children }: PropsWithChildren): react.FunctionComponentElement<react.ProviderProps<boolean>>;
|
|
105
|
+
declare function useRedpacketReady(): boolean;
|
|
106
|
+
|
|
107
|
+
export { type ClaimRedPacketIntent, type CreateFixedAmountRedPacketIntent, type CreateRandomAmountRedPacketIntent, PACKAGE_NAME, type RedpacketCommand, type RedpacketExecutionPort, type RedpacketIntentStatus, type RedpacketPacketStatus, RedpacketProvider, type RedpacketRecord, type RedpacketSignerPort, type RedpacketSnapshot, createInMemoryRedpacketPorts, createRedpacketRuntime, redPacketQueryKeys, redpacketRecordStatus, useRedpacketReady, validateRedpacketCommand };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { PropsWithChildren } from 'react';
|
|
3
|
+
import { Chain } from '@liberfi.io/types';
|
|
4
|
+
|
|
5
|
+
declare const redPacketQueryKeys: {
|
|
6
|
+
packet: (idOrShareId: string) => readonly ["redPacket", string];
|
|
7
|
+
walletClaims: (address: string, cursor?: string) => readonly ["walletClaims", string, string];
|
|
8
|
+
packetClaims: (redPacketId: string, cursor?: string) => readonly ["redPacketClaims", string, string];
|
|
9
|
+
walletPackets: (address: string, cursor?: string) => readonly ["walletRedPackets", string, string];
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
interface CreateFixedAmountRedPacketIntent {
|
|
13
|
+
chain: Chain;
|
|
14
|
+
creator: string;
|
|
15
|
+
mint: string;
|
|
16
|
+
maxClaims: number;
|
|
17
|
+
fixedAmount: string;
|
|
18
|
+
memo?: string;
|
|
19
|
+
password?: string;
|
|
20
|
+
}
|
|
21
|
+
interface CreateRandomAmountRedPacketIntent {
|
|
22
|
+
chain: Chain;
|
|
23
|
+
creator: string;
|
|
24
|
+
mint: string;
|
|
25
|
+
maxClaims: number;
|
|
26
|
+
totalAmount: string;
|
|
27
|
+
memo?: string;
|
|
28
|
+
password?: string;
|
|
29
|
+
}
|
|
30
|
+
interface ClaimRedPacketIntent {
|
|
31
|
+
chain: Chain;
|
|
32
|
+
shareId: string;
|
|
33
|
+
claimer: string;
|
|
34
|
+
password?: string;
|
|
35
|
+
}
|
|
36
|
+
type RedpacketPacketStatus = "ongoing" | "finished" | "expired";
|
|
37
|
+
interface RedpacketRecord {
|
|
38
|
+
id: string;
|
|
39
|
+
shareId: string;
|
|
40
|
+
status: RedpacketPacketStatus;
|
|
41
|
+
totalAmount: string;
|
|
42
|
+
claimedAmount?: string;
|
|
43
|
+
claimedCount?: number;
|
|
44
|
+
maxClaims: number;
|
|
45
|
+
memo?: string;
|
|
46
|
+
mint?: string;
|
|
47
|
+
creator?: string;
|
|
48
|
+
expiredAt?: number;
|
|
49
|
+
}
|
|
50
|
+
declare function redpacketRecordStatus(record: Pick<RedpacketRecord, "claimedAmount" | "totalAmount" | "claimedCount" | "maxClaims" | "expiredAt">): RedpacketPacketStatus;
|
|
51
|
+
type RedpacketIntentStatus = "idle" | "validating" | "signing" | "submitting" | "succeeded" | "failed" | "rejected" | "already-claimed";
|
|
52
|
+
|
|
53
|
+
type RedpacketCommand = {
|
|
54
|
+
kind: "create-fixed";
|
|
55
|
+
intent: CreateFixedAmountRedPacketIntent;
|
|
56
|
+
} | {
|
|
57
|
+
kind: "create-random";
|
|
58
|
+
intent: CreateRandomAmountRedPacketIntent;
|
|
59
|
+
} | {
|
|
60
|
+
kind: "claim";
|
|
61
|
+
intent: ClaimRedPacketIntent;
|
|
62
|
+
};
|
|
63
|
+
interface RedpacketSnapshot {
|
|
64
|
+
status: RedpacketIntentStatus;
|
|
65
|
+
command?: RedpacketCommand;
|
|
66
|
+
packetId?: string;
|
|
67
|
+
error?: Error;
|
|
68
|
+
}
|
|
69
|
+
interface RedpacketSignerPort {
|
|
70
|
+
sign(command: RedpacketCommand): Promise<string>;
|
|
71
|
+
}
|
|
72
|
+
interface RedpacketExecutionPort {
|
|
73
|
+
submit(signed: string, command: RedpacketCommand): Promise<{
|
|
74
|
+
packetId: string;
|
|
75
|
+
alreadyClaimed?: boolean;
|
|
76
|
+
}>;
|
|
77
|
+
}
|
|
78
|
+
declare function validateRedpacketCommand(command: RedpacketCommand): void;
|
|
79
|
+
declare function createRedpacketRuntime(options: {
|
|
80
|
+
signer?: RedpacketSignerPort;
|
|
81
|
+
execution: RedpacketExecutionPort;
|
|
82
|
+
onChange?: (snapshot: RedpacketSnapshot) => void;
|
|
83
|
+
}): {
|
|
84
|
+
snapshot(): RedpacketSnapshot;
|
|
85
|
+
submit(command: RedpacketCommand): Promise<RedpacketSnapshot>;
|
|
86
|
+
};
|
|
87
|
+
declare function createInMemoryRedpacketPorts(options?: {
|
|
88
|
+
signError?: Error;
|
|
89
|
+
alreadyClaimed?: boolean;
|
|
90
|
+
timeout?: boolean;
|
|
91
|
+
}): {
|
|
92
|
+
signer: {
|
|
93
|
+
sign(): Promise<string>;
|
|
94
|
+
};
|
|
95
|
+
execution: {
|
|
96
|
+
submit(signed: string, command: RedpacketCommand): Promise<{
|
|
97
|
+
packetId: string;
|
|
98
|
+
alreadyClaimed: boolean | undefined;
|
|
99
|
+
}>;
|
|
100
|
+
};
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
declare const PACKAGE_NAME: "@liberfi.io/react-redpacket";
|
|
104
|
+
declare function RedpacketProvider({ children }: PropsWithChildren): react.FunctionComponentElement<react.ProviderProps<boolean>>;
|
|
105
|
+
declare function useRedpacketReady(): boolean;
|
|
106
|
+
|
|
107
|
+
export { type ClaimRedPacketIntent, type CreateFixedAmountRedPacketIntent, type CreateRandomAmountRedPacketIntent, PACKAGE_NAME, type RedpacketCommand, type RedpacketExecutionPort, type RedpacketIntentStatus, type RedpacketPacketStatus, RedpacketProvider, type RedpacketRecord, type RedpacketSignerPort, type RedpacketSnapshot, createInMemoryRedpacketPorts, createRedpacketRuntime, redPacketQueryKeys, redpacketRecordStatus, useRedpacketReady, validateRedpacketCommand };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var react = require('react');
|
|
4
|
+
|
|
5
|
+
// src/index.ts
|
|
6
|
+
|
|
7
|
+
// src/query-keys.ts
|
|
8
|
+
var redPacketQueryKeys = {
|
|
9
|
+
packet: (idOrShareId) => ["redPacket", idOrShareId],
|
|
10
|
+
walletClaims: (address, cursor = "") => ["walletClaims", address, cursor],
|
|
11
|
+
packetClaims: (redPacketId, cursor = "") => ["redPacketClaims", redPacketId, cursor],
|
|
12
|
+
walletPackets: (address, cursor = "") => ["walletRedPackets", address, cursor]
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
// src/types.ts
|
|
16
|
+
function redpacketRecordStatus(record) {
|
|
17
|
+
if (Number(record.claimedAmount ?? 0) >= Number(record.totalAmount) || (record.claimedCount ?? 0) >= record.maxClaims) {
|
|
18
|
+
return "finished";
|
|
19
|
+
}
|
|
20
|
+
if ((record.expiredAt ?? Number.POSITIVE_INFINITY) > Date.now()) {
|
|
21
|
+
return "ongoing";
|
|
22
|
+
}
|
|
23
|
+
return "expired";
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// src/redpacket-runtime.ts
|
|
27
|
+
function validateRedpacketCommand(command) {
|
|
28
|
+
if (command.kind === "create-fixed") {
|
|
29
|
+
const n = Number(command.intent.fixedAmount);
|
|
30
|
+
if (!Number.isFinite(n) || n <= 0) throw new Error("invalid amount");
|
|
31
|
+
if (command.intent.maxClaims < 1) throw new Error("invalid claim count");
|
|
32
|
+
}
|
|
33
|
+
if (command.kind === "create-random") {
|
|
34
|
+
const n = Number(command.intent.totalAmount);
|
|
35
|
+
if (!Number.isFinite(n) || n <= 0) throw new Error("invalid amount");
|
|
36
|
+
if (command.intent.maxClaims < 1) throw new Error("invalid claim count");
|
|
37
|
+
}
|
|
38
|
+
if (command.kind === "claim" && !command.intent.shareId) {
|
|
39
|
+
throw new Error("missing packet");
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function createRedpacketRuntime(options) {
|
|
43
|
+
let current = { status: "idle" };
|
|
44
|
+
const claimed = /* @__PURE__ */ new Set();
|
|
45
|
+
const set = (next) => {
|
|
46
|
+
current = next;
|
|
47
|
+
options.onChange?.(next);
|
|
48
|
+
return next;
|
|
49
|
+
};
|
|
50
|
+
return {
|
|
51
|
+
snapshot() {
|
|
52
|
+
return current;
|
|
53
|
+
},
|
|
54
|
+
async submit(command) {
|
|
55
|
+
if (command.kind === "claim" && claimed.has(command.intent.shareId)) {
|
|
56
|
+
return set({
|
|
57
|
+
status: "already-claimed",
|
|
58
|
+
command,
|
|
59
|
+
error: new Error("already claimed")
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
set({ status: "validating", command });
|
|
63
|
+
try {
|
|
64
|
+
validateRedpacketCommand(command);
|
|
65
|
+
} catch (error) {
|
|
66
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
67
|
+
return set({ status: "failed", command, error: err });
|
|
68
|
+
}
|
|
69
|
+
if (!options.signer) {
|
|
70
|
+
return set({
|
|
71
|
+
status: "rejected",
|
|
72
|
+
command,
|
|
73
|
+
error: new Error("missing signer")
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
set({ status: "signing", command });
|
|
77
|
+
let signed;
|
|
78
|
+
try {
|
|
79
|
+
signed = await options.signer.sign(command);
|
|
80
|
+
} catch (error) {
|
|
81
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
82
|
+
return set({ status: "rejected", command, error: err });
|
|
83
|
+
}
|
|
84
|
+
set({ status: "submitting", command });
|
|
85
|
+
try {
|
|
86
|
+
const result = await options.execution.submit(signed, command);
|
|
87
|
+
if (result.alreadyClaimed) {
|
|
88
|
+
claimed.add(command.kind === "claim" ? command.intent.shareId : result.packetId);
|
|
89
|
+
return set({
|
|
90
|
+
status: "already-claimed",
|
|
91
|
+
command,
|
|
92
|
+
packetId: result.packetId
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
if (command.kind === "claim") claimed.add(command.intent.shareId);
|
|
96
|
+
return set({
|
|
97
|
+
status: "succeeded",
|
|
98
|
+
command,
|
|
99
|
+
packetId: result.packetId
|
|
100
|
+
});
|
|
101
|
+
} catch (error) {
|
|
102
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
103
|
+
return set({ status: "failed", command, error: err });
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
function createInMemoryRedpacketPorts(options = {}) {
|
|
109
|
+
return {
|
|
110
|
+
signer: {
|
|
111
|
+
async sign() {
|
|
112
|
+
if (options.signError) throw options.signError;
|
|
113
|
+
return "signed";
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
execution: {
|
|
117
|
+
async submit(signed, command) {
|
|
118
|
+
if (options.timeout) throw new Error("submit timeout");
|
|
119
|
+
return {
|
|
120
|
+
packetId: command.kind === "claim" ? command.intent.shareId : "packet-memory",
|
|
121
|
+
alreadyClaimed: options.alreadyClaimed
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// src/index.ts
|
|
129
|
+
var PACKAGE_NAME = "@liberfi.io/react-redpacket";
|
|
130
|
+
var ReadyContext = react.createContext(true);
|
|
131
|
+
function RedpacketProvider({ children }) {
|
|
132
|
+
return react.createElement(ReadyContext.Provider, { value: true }, children);
|
|
133
|
+
}
|
|
134
|
+
function useRedpacketReady() {
|
|
135
|
+
return react.useContext(ReadyContext);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
exports.PACKAGE_NAME = PACKAGE_NAME;
|
|
139
|
+
exports.RedpacketProvider = RedpacketProvider;
|
|
140
|
+
exports.createInMemoryRedpacketPorts = createInMemoryRedpacketPorts;
|
|
141
|
+
exports.createRedpacketRuntime = createRedpacketRuntime;
|
|
142
|
+
exports.redPacketQueryKeys = redPacketQueryKeys;
|
|
143
|
+
exports.redpacketRecordStatus = redpacketRecordStatus;
|
|
144
|
+
exports.useRedpacketReady = useRedpacketReady;
|
|
145
|
+
exports.validateRedpacketCommand = validateRedpacketCommand;
|
|
146
|
+
//# sourceMappingURL=index.js.map
|
|
147
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/query-keys.ts","../src/types.ts","../src/redpacket-runtime.ts","../src/index.ts"],"names":["createContext","createElement","useContext"],"mappings":"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","file":"index.js","sourcesContent":["export const redPacketQueryKeys = {\n packet: (idOrShareId: string) => [\"redPacket\", idOrShareId] as const,\n walletClaims: (address: string, cursor = \"\") =>\n [\"walletClaims\", address, cursor] as const,\n packetClaims: (redPacketId: string, cursor = \"\") =>\n [\"redPacketClaims\", redPacketId, cursor] as const,\n walletPackets: (address: string, cursor = \"\") =>\n [\"walletRedPackets\", address, cursor] as const,\n};\n","import type { Chain } from \"@liberfi.io/types\";\n\nexport interface CreateFixedAmountRedPacketIntent {\n chain: Chain;\n creator: string;\n mint: string;\n maxClaims: number;\n fixedAmount: string;\n memo?: string;\n password?: string;\n}\n\nexport interface CreateRandomAmountRedPacketIntent {\n chain: Chain;\n creator: string;\n mint: string;\n maxClaims: number;\n totalAmount: string;\n memo?: string;\n password?: string;\n}\n\nexport interface ClaimRedPacketIntent {\n chain: Chain;\n shareId: string;\n claimer: string;\n password?: string;\n}\n\nexport type RedpacketPacketStatus = \"ongoing\" | \"finished\" | \"expired\";\n\nexport interface RedpacketRecord {\n id: string;\n shareId: string;\n status: RedpacketPacketStatus;\n totalAmount: string;\n claimedAmount?: string;\n claimedCount?: number;\n maxClaims: number;\n memo?: string;\n mint?: string;\n creator?: string;\n expiredAt?: number;\n}\n\nexport function redpacketRecordStatus(\n record: Pick<\n RedpacketRecord,\n \"claimedAmount\" | \"totalAmount\" | \"claimedCount\" | \"maxClaims\" | \"expiredAt\"\n >,\n): RedpacketPacketStatus {\n if (\n Number(record.claimedAmount ?? 0) >= Number(record.totalAmount) ||\n (record.claimedCount ?? 0) >= record.maxClaims\n ) {\n return \"finished\";\n }\n if ((record.expiredAt ?? Number.POSITIVE_INFINITY) > Date.now()) {\n return \"ongoing\";\n }\n return \"expired\";\n}\n\nexport type RedpacketIntentStatus =\n | \"idle\"\n | \"validating\"\n | \"signing\"\n | \"submitting\"\n | \"succeeded\"\n | \"failed\"\n | \"rejected\"\n | \"already-claimed\";\n","import type {\n ClaimRedPacketIntent,\n CreateFixedAmountRedPacketIntent,\n CreateRandomAmountRedPacketIntent,\n RedpacketIntentStatus,\n} from \"./types\";\n\nexport type RedpacketCommand =\n | { kind: \"create-fixed\"; intent: CreateFixedAmountRedPacketIntent }\n | { kind: \"create-random\"; intent: CreateRandomAmountRedPacketIntent }\n | { kind: \"claim\"; intent: ClaimRedPacketIntent };\n\nexport interface RedpacketSnapshot {\n status: RedpacketIntentStatus;\n command?: RedpacketCommand;\n packetId?: string;\n error?: Error;\n}\n\nexport interface RedpacketSignerPort {\n sign(command: RedpacketCommand): Promise<string>;\n}\n\nexport interface RedpacketExecutionPort {\n submit(\n signed: string,\n command: RedpacketCommand,\n ): Promise<{ packetId: string; alreadyClaimed?: boolean }>;\n}\n\nexport function validateRedpacketCommand(command: RedpacketCommand): void {\n if (command.kind === \"create-fixed\") {\n const n = Number(command.intent.fixedAmount);\n if (!Number.isFinite(n) || n <= 0) throw new Error(\"invalid amount\");\n if (command.intent.maxClaims < 1) throw new Error(\"invalid claim count\");\n }\n if (command.kind === \"create-random\") {\n const n = Number(command.intent.totalAmount);\n if (!Number.isFinite(n) || n <= 0) throw new Error(\"invalid amount\");\n if (command.intent.maxClaims < 1) throw new Error(\"invalid claim count\");\n }\n if (command.kind === \"claim\" && !command.intent.shareId) {\n throw new Error(\"missing packet\");\n }\n}\n\nexport function createRedpacketRuntime(options: {\n signer?: RedpacketSignerPort;\n execution: RedpacketExecutionPort;\n onChange?: (snapshot: RedpacketSnapshot) => void;\n}) {\n let current: RedpacketSnapshot = { status: \"idle\" };\n const claimed = new Set<string>();\n const set = (next: RedpacketSnapshot) => {\n current = next;\n options.onChange?.(next);\n return next;\n };\n\n return {\n snapshot() {\n return current;\n },\n async submit(command: RedpacketCommand) {\n if (command.kind === \"claim\" && claimed.has(command.intent.shareId)) {\n return set({\n status: \"already-claimed\",\n command,\n error: new Error(\"already claimed\"),\n });\n }\n set({ status: \"validating\", command });\n try {\n validateRedpacketCommand(command);\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n return set({ status: \"failed\", command, error: err });\n }\n if (!options.signer) {\n return set({\n status: \"rejected\",\n command,\n error: new Error(\"missing signer\"),\n });\n }\n set({ status: \"signing\", command });\n let signed: string;\n try {\n signed = await options.signer.sign(command);\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n return set({ status: \"rejected\", command, error: err });\n }\n set({ status: \"submitting\", command });\n try {\n const result = await options.execution.submit(signed, command);\n if (result.alreadyClaimed) {\n claimed.add(command.kind === \"claim\" ? command.intent.shareId : result.packetId);\n return set({\n status: \"already-claimed\",\n command,\n packetId: result.packetId,\n });\n }\n if (command.kind === \"claim\") claimed.add(command.intent.shareId);\n return set({\n status: \"succeeded\",\n command,\n packetId: result.packetId,\n });\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n return set({ status: \"failed\", command, error: err });\n }\n },\n };\n}\n\nexport function createInMemoryRedpacketPorts(options: {\n signError?: Error;\n alreadyClaimed?: boolean;\n timeout?: boolean;\n} = {}) {\n return {\n signer: {\n async sign() {\n if (options.signError) throw options.signError;\n return \"signed\";\n },\n },\n execution: {\n async submit(signed: string, command: RedpacketCommand) {\n void signed;\n if (options.timeout) throw new Error(\"submit timeout\");\n return {\n packetId:\n command.kind === \"claim\" ? command.intent.shareId : \"packet-memory\",\n alreadyClaimed: options.alreadyClaimed,\n };\n },\n },\n };\n}\n","import {\n createContext,\n createElement,\n useContext,\n type PropsWithChildren,\n} from \"react\";\n\nexport const PACKAGE_NAME = \"@liberfi.io/react-redpacket\" as const;\n\nconst ReadyContext = createContext(true);\n\nexport function RedpacketProvider({ children }: PropsWithChildren) {\n return createElement(ReadyContext.Provider, { value: true }, children);\n}\n\nexport function useRedpacketReady(): boolean {\n return useContext(ReadyContext);\n}\n\nexport { redPacketQueryKeys } from \"./query-keys\";\nexport type {\n ClaimRedPacketIntent,\n CreateFixedAmountRedPacketIntent,\n CreateRandomAmountRedPacketIntent,\n RedpacketIntentStatus,\n RedpacketPacketStatus,\n RedpacketRecord,\n} from \"./types\";\nexport { redpacketRecordStatus } from \"./types\";\nexport {\n createInMemoryRedpacketPorts,\n createRedpacketRuntime,\n validateRedpacketCommand,\n} from \"./redpacket-runtime\";\nexport type {\n RedpacketCommand,\n RedpacketExecutionPort,\n RedpacketSignerPort,\n RedpacketSnapshot,\n} from \"./redpacket-runtime\";\n"]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { createContext, createElement, useContext } from 'react';
|
|
2
|
+
|
|
3
|
+
// src/index.ts
|
|
4
|
+
|
|
5
|
+
// src/query-keys.ts
|
|
6
|
+
var redPacketQueryKeys = {
|
|
7
|
+
packet: (idOrShareId) => ["redPacket", idOrShareId],
|
|
8
|
+
walletClaims: (address, cursor = "") => ["walletClaims", address, cursor],
|
|
9
|
+
packetClaims: (redPacketId, cursor = "") => ["redPacketClaims", redPacketId, cursor],
|
|
10
|
+
walletPackets: (address, cursor = "") => ["walletRedPackets", address, cursor]
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
// src/types.ts
|
|
14
|
+
function redpacketRecordStatus(record) {
|
|
15
|
+
if (Number(record.claimedAmount ?? 0) >= Number(record.totalAmount) || (record.claimedCount ?? 0) >= record.maxClaims) {
|
|
16
|
+
return "finished";
|
|
17
|
+
}
|
|
18
|
+
if ((record.expiredAt ?? Number.POSITIVE_INFINITY) > Date.now()) {
|
|
19
|
+
return "ongoing";
|
|
20
|
+
}
|
|
21
|
+
return "expired";
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// src/redpacket-runtime.ts
|
|
25
|
+
function validateRedpacketCommand(command) {
|
|
26
|
+
if (command.kind === "create-fixed") {
|
|
27
|
+
const n = Number(command.intent.fixedAmount);
|
|
28
|
+
if (!Number.isFinite(n) || n <= 0) throw new Error("invalid amount");
|
|
29
|
+
if (command.intent.maxClaims < 1) throw new Error("invalid claim count");
|
|
30
|
+
}
|
|
31
|
+
if (command.kind === "create-random") {
|
|
32
|
+
const n = Number(command.intent.totalAmount);
|
|
33
|
+
if (!Number.isFinite(n) || n <= 0) throw new Error("invalid amount");
|
|
34
|
+
if (command.intent.maxClaims < 1) throw new Error("invalid claim count");
|
|
35
|
+
}
|
|
36
|
+
if (command.kind === "claim" && !command.intent.shareId) {
|
|
37
|
+
throw new Error("missing packet");
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function createRedpacketRuntime(options) {
|
|
41
|
+
let current = { status: "idle" };
|
|
42
|
+
const claimed = /* @__PURE__ */ new Set();
|
|
43
|
+
const set = (next) => {
|
|
44
|
+
current = next;
|
|
45
|
+
options.onChange?.(next);
|
|
46
|
+
return next;
|
|
47
|
+
};
|
|
48
|
+
return {
|
|
49
|
+
snapshot() {
|
|
50
|
+
return current;
|
|
51
|
+
},
|
|
52
|
+
async submit(command) {
|
|
53
|
+
if (command.kind === "claim" && claimed.has(command.intent.shareId)) {
|
|
54
|
+
return set({
|
|
55
|
+
status: "already-claimed",
|
|
56
|
+
command,
|
|
57
|
+
error: new Error("already claimed")
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
set({ status: "validating", command });
|
|
61
|
+
try {
|
|
62
|
+
validateRedpacketCommand(command);
|
|
63
|
+
} catch (error) {
|
|
64
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
65
|
+
return set({ status: "failed", command, error: err });
|
|
66
|
+
}
|
|
67
|
+
if (!options.signer) {
|
|
68
|
+
return set({
|
|
69
|
+
status: "rejected",
|
|
70
|
+
command,
|
|
71
|
+
error: new Error("missing signer")
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
set({ status: "signing", command });
|
|
75
|
+
let signed;
|
|
76
|
+
try {
|
|
77
|
+
signed = await options.signer.sign(command);
|
|
78
|
+
} catch (error) {
|
|
79
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
80
|
+
return set({ status: "rejected", command, error: err });
|
|
81
|
+
}
|
|
82
|
+
set({ status: "submitting", command });
|
|
83
|
+
try {
|
|
84
|
+
const result = await options.execution.submit(signed, command);
|
|
85
|
+
if (result.alreadyClaimed) {
|
|
86
|
+
claimed.add(command.kind === "claim" ? command.intent.shareId : result.packetId);
|
|
87
|
+
return set({
|
|
88
|
+
status: "already-claimed",
|
|
89
|
+
command,
|
|
90
|
+
packetId: result.packetId
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
if (command.kind === "claim") claimed.add(command.intent.shareId);
|
|
94
|
+
return set({
|
|
95
|
+
status: "succeeded",
|
|
96
|
+
command,
|
|
97
|
+
packetId: result.packetId
|
|
98
|
+
});
|
|
99
|
+
} catch (error) {
|
|
100
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
101
|
+
return set({ status: "failed", command, error: err });
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
function createInMemoryRedpacketPorts(options = {}) {
|
|
107
|
+
return {
|
|
108
|
+
signer: {
|
|
109
|
+
async sign() {
|
|
110
|
+
if (options.signError) throw options.signError;
|
|
111
|
+
return "signed";
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
execution: {
|
|
115
|
+
async submit(signed, command) {
|
|
116
|
+
if (options.timeout) throw new Error("submit timeout");
|
|
117
|
+
return {
|
|
118
|
+
packetId: command.kind === "claim" ? command.intent.shareId : "packet-memory",
|
|
119
|
+
alreadyClaimed: options.alreadyClaimed
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// src/index.ts
|
|
127
|
+
var PACKAGE_NAME = "@liberfi.io/react-redpacket";
|
|
128
|
+
var ReadyContext = createContext(true);
|
|
129
|
+
function RedpacketProvider({ children }) {
|
|
130
|
+
return createElement(ReadyContext.Provider, { value: true }, children);
|
|
131
|
+
}
|
|
132
|
+
function useRedpacketReady() {
|
|
133
|
+
return useContext(ReadyContext);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export { PACKAGE_NAME, RedpacketProvider, createInMemoryRedpacketPorts, createRedpacketRuntime, redPacketQueryKeys, redpacketRecordStatus, useRedpacketReady, validateRedpacketCommand };
|
|
137
|
+
//# sourceMappingURL=index.mjs.map
|
|
138
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/query-keys.ts","../src/types.ts","../src/redpacket-runtime.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["export const redPacketQueryKeys = {\n packet: (idOrShareId: string) => [\"redPacket\", idOrShareId] as const,\n walletClaims: (address: string, cursor = \"\") =>\n [\"walletClaims\", address, cursor] as const,\n packetClaims: (redPacketId: string, cursor = \"\") =>\n [\"redPacketClaims\", redPacketId, cursor] as const,\n walletPackets: (address: string, cursor = \"\") =>\n [\"walletRedPackets\", address, cursor] as const,\n};\n","import type { Chain } from \"@liberfi.io/types\";\n\nexport interface CreateFixedAmountRedPacketIntent {\n chain: Chain;\n creator: string;\n mint: string;\n maxClaims: number;\n fixedAmount: string;\n memo?: string;\n password?: string;\n}\n\nexport interface CreateRandomAmountRedPacketIntent {\n chain: Chain;\n creator: string;\n mint: string;\n maxClaims: number;\n totalAmount: string;\n memo?: string;\n password?: string;\n}\n\nexport interface ClaimRedPacketIntent {\n chain: Chain;\n shareId: string;\n claimer: string;\n password?: string;\n}\n\nexport type RedpacketPacketStatus = \"ongoing\" | \"finished\" | \"expired\";\n\nexport interface RedpacketRecord {\n id: string;\n shareId: string;\n status: RedpacketPacketStatus;\n totalAmount: string;\n claimedAmount?: string;\n claimedCount?: number;\n maxClaims: number;\n memo?: string;\n mint?: string;\n creator?: string;\n expiredAt?: number;\n}\n\nexport function redpacketRecordStatus(\n record: Pick<\n RedpacketRecord,\n \"claimedAmount\" | \"totalAmount\" | \"claimedCount\" | \"maxClaims\" | \"expiredAt\"\n >,\n): RedpacketPacketStatus {\n if (\n Number(record.claimedAmount ?? 0) >= Number(record.totalAmount) ||\n (record.claimedCount ?? 0) >= record.maxClaims\n ) {\n return \"finished\";\n }\n if ((record.expiredAt ?? Number.POSITIVE_INFINITY) > Date.now()) {\n return \"ongoing\";\n }\n return \"expired\";\n}\n\nexport type RedpacketIntentStatus =\n | \"idle\"\n | \"validating\"\n | \"signing\"\n | \"submitting\"\n | \"succeeded\"\n | \"failed\"\n | \"rejected\"\n | \"already-claimed\";\n","import type {\n ClaimRedPacketIntent,\n CreateFixedAmountRedPacketIntent,\n CreateRandomAmountRedPacketIntent,\n RedpacketIntentStatus,\n} from \"./types\";\n\nexport type RedpacketCommand =\n | { kind: \"create-fixed\"; intent: CreateFixedAmountRedPacketIntent }\n | { kind: \"create-random\"; intent: CreateRandomAmountRedPacketIntent }\n | { kind: \"claim\"; intent: ClaimRedPacketIntent };\n\nexport interface RedpacketSnapshot {\n status: RedpacketIntentStatus;\n command?: RedpacketCommand;\n packetId?: string;\n error?: Error;\n}\n\nexport interface RedpacketSignerPort {\n sign(command: RedpacketCommand): Promise<string>;\n}\n\nexport interface RedpacketExecutionPort {\n submit(\n signed: string,\n command: RedpacketCommand,\n ): Promise<{ packetId: string; alreadyClaimed?: boolean }>;\n}\n\nexport function validateRedpacketCommand(command: RedpacketCommand): void {\n if (command.kind === \"create-fixed\") {\n const n = Number(command.intent.fixedAmount);\n if (!Number.isFinite(n) || n <= 0) throw new Error(\"invalid amount\");\n if (command.intent.maxClaims < 1) throw new Error(\"invalid claim count\");\n }\n if (command.kind === \"create-random\") {\n const n = Number(command.intent.totalAmount);\n if (!Number.isFinite(n) || n <= 0) throw new Error(\"invalid amount\");\n if (command.intent.maxClaims < 1) throw new Error(\"invalid claim count\");\n }\n if (command.kind === \"claim\" && !command.intent.shareId) {\n throw new Error(\"missing packet\");\n }\n}\n\nexport function createRedpacketRuntime(options: {\n signer?: RedpacketSignerPort;\n execution: RedpacketExecutionPort;\n onChange?: (snapshot: RedpacketSnapshot) => void;\n}) {\n let current: RedpacketSnapshot = { status: \"idle\" };\n const claimed = new Set<string>();\n const set = (next: RedpacketSnapshot) => {\n current = next;\n options.onChange?.(next);\n return next;\n };\n\n return {\n snapshot() {\n return current;\n },\n async submit(command: RedpacketCommand) {\n if (command.kind === \"claim\" && claimed.has(command.intent.shareId)) {\n return set({\n status: \"already-claimed\",\n command,\n error: new Error(\"already claimed\"),\n });\n }\n set({ status: \"validating\", command });\n try {\n validateRedpacketCommand(command);\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n return set({ status: \"failed\", command, error: err });\n }\n if (!options.signer) {\n return set({\n status: \"rejected\",\n command,\n error: new Error(\"missing signer\"),\n });\n }\n set({ status: \"signing\", command });\n let signed: string;\n try {\n signed = await options.signer.sign(command);\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n return set({ status: \"rejected\", command, error: err });\n }\n set({ status: \"submitting\", command });\n try {\n const result = await options.execution.submit(signed, command);\n if (result.alreadyClaimed) {\n claimed.add(command.kind === \"claim\" ? command.intent.shareId : result.packetId);\n return set({\n status: \"already-claimed\",\n command,\n packetId: result.packetId,\n });\n }\n if (command.kind === \"claim\") claimed.add(command.intent.shareId);\n return set({\n status: \"succeeded\",\n command,\n packetId: result.packetId,\n });\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n return set({ status: \"failed\", command, error: err });\n }\n },\n };\n}\n\nexport function createInMemoryRedpacketPorts(options: {\n signError?: Error;\n alreadyClaimed?: boolean;\n timeout?: boolean;\n} = {}) {\n return {\n signer: {\n async sign() {\n if (options.signError) throw options.signError;\n return \"signed\";\n },\n },\n execution: {\n async submit(signed: string, command: RedpacketCommand) {\n void signed;\n if (options.timeout) throw new Error(\"submit timeout\");\n return {\n packetId:\n command.kind === \"claim\" ? command.intent.shareId : \"packet-memory\",\n alreadyClaimed: options.alreadyClaimed,\n };\n },\n },\n };\n}\n","import {\n createContext,\n createElement,\n useContext,\n type PropsWithChildren,\n} from \"react\";\n\nexport const PACKAGE_NAME = \"@liberfi.io/react-redpacket\" as const;\n\nconst ReadyContext = createContext(true);\n\nexport function RedpacketProvider({ children }: PropsWithChildren) {\n return createElement(ReadyContext.Provider, { value: true }, children);\n}\n\nexport function useRedpacketReady(): boolean {\n return useContext(ReadyContext);\n}\n\nexport { redPacketQueryKeys } from \"./query-keys\";\nexport type {\n ClaimRedPacketIntent,\n CreateFixedAmountRedPacketIntent,\n CreateRandomAmountRedPacketIntent,\n RedpacketIntentStatus,\n RedpacketPacketStatus,\n RedpacketRecord,\n} from \"./types\";\nexport { redpacketRecordStatus } from \"./types\";\nexport {\n createInMemoryRedpacketPorts,\n createRedpacketRuntime,\n validateRedpacketCommand,\n} from \"./redpacket-runtime\";\nexport type {\n RedpacketCommand,\n RedpacketExecutionPort,\n RedpacketSignerPort,\n RedpacketSnapshot,\n} from \"./redpacket-runtime\";\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@liberfi.io/react-redpacket",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Redpacket domain runtime and React bindings",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": {
|
|
11
|
+
"types": "./dist/index.d.mts",
|
|
12
|
+
"default": "./dist/index.mjs"
|
|
13
|
+
},
|
|
14
|
+
"require": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"default": "./dist/index.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"./package.json": "./package.json"
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist"
|
|
23
|
+
],
|
|
24
|
+
"peerDependencies": {
|
|
25
|
+
"@tanstack/react-query": ">=5",
|
|
26
|
+
"react": ">=18",
|
|
27
|
+
"react-dom": ">=18"
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@liberfi.io/types": "0.4.74",
|
|
31
|
+
"@liberfi.io/utils": "0.2.73"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@tanstack/react-query": "^5.90.2",
|
|
35
|
+
"@testing-library/jest-dom": "^6.9.1",
|
|
36
|
+
"@testing-library/react": "^16.3.0",
|
|
37
|
+
"@types/jest": "^30.0.0",
|
|
38
|
+
"@types/react": "^19.1.13",
|
|
39
|
+
"@types/react-dom": "^19.1.9",
|
|
40
|
+
"jest": "^30.2.0",
|
|
41
|
+
"jest-environment-jsdom": "^30.2.0",
|
|
42
|
+
"react": "^19.1.1",
|
|
43
|
+
"react-dom": "^19.1.1",
|
|
44
|
+
"rimraf": "^5.0.5",
|
|
45
|
+
"ts-jest": "^29.4.5",
|
|
46
|
+
"tsup": "^8.5.0",
|
|
47
|
+
"typescript": "^5.9.2",
|
|
48
|
+
"tsconfig": "0.1.257"
|
|
49
|
+
},
|
|
50
|
+
"publishConfig": {
|
|
51
|
+
"access": "public"
|
|
52
|
+
},
|
|
53
|
+
"scripts": {
|
|
54
|
+
"dev": "tsup --watch",
|
|
55
|
+
"build": "rimraf -rf dist && tsup",
|
|
56
|
+
"test": "jest --config jest.config.cjs --runInBand --detectOpenHandles",
|
|
57
|
+
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
58
|
+
"lint": "eslint src"
|
|
59
|
+
}
|
|
60
|
+
}
|