@merkl/api 0.16.14 → 0.16.15

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.
@@ -0,0 +1,216 @@
1
+ export declare abstract class ReferralService {
2
+ #private;
3
+ static abi: readonly [{
4
+ readonly name: "getReferralKeys";
5
+ readonly type: "function";
6
+ readonly stateMutability: "view";
7
+ readonly inputs: readonly [];
8
+ readonly outputs: readonly [{
9
+ readonly type: "string[]";
10
+ }];
11
+ }, {
12
+ readonly name: "getReferrerStatus";
13
+ readonly type: "function";
14
+ readonly stateMutability: "view";
15
+ readonly inputs: readonly [{
16
+ readonly type: "string";
17
+ readonly name: "key";
18
+ }, {
19
+ readonly type: "address";
20
+ readonly name: "user";
21
+ }];
22
+ readonly outputs: readonly [{
23
+ readonly type: "bytes32";
24
+ }];
25
+ }, {
26
+ readonly name: "referrerCodeMapping";
27
+ readonly type: "function";
28
+ readonly stateMutability: "view";
29
+ readonly inputs: readonly [{
30
+ readonly type: "string";
31
+ readonly name: "key";
32
+ }, {
33
+ readonly type: "address";
34
+ readonly name: "user";
35
+ }];
36
+ readonly outputs: readonly [{
37
+ readonly type: "string";
38
+ }];
39
+ }, {
40
+ readonly name: "codeToReferrer";
41
+ readonly type: "function";
42
+ readonly stateMutability: "view";
43
+ readonly inputs: readonly [{
44
+ readonly type: "string";
45
+ readonly name: "key";
46
+ }, {
47
+ readonly type: "string";
48
+ readonly name: "user";
49
+ }];
50
+ readonly outputs: readonly [{
51
+ readonly type: "address";
52
+ }];
53
+ }, {
54
+ readonly name: "getReferrer";
55
+ readonly type: "function";
56
+ readonly stateMutability: "view";
57
+ readonly inputs: readonly [{
58
+ readonly type: "string";
59
+ readonly name: "key";
60
+ }, {
61
+ readonly type: "address";
62
+ readonly name: "user";
63
+ }];
64
+ readonly outputs: readonly [{
65
+ readonly type: "address";
66
+ }];
67
+ }, {
68
+ readonly name: "getReferredUsers";
69
+ readonly type: "function";
70
+ readonly stateMutability: "view";
71
+ readonly inputs: readonly [{
72
+ readonly type: "string";
73
+ readonly name: "key";
74
+ }, {
75
+ readonly type: "address";
76
+ readonly name: "user";
77
+ }];
78
+ readonly outputs: readonly [{
79
+ readonly type: "address[]";
80
+ }];
81
+ }, {
82
+ readonly name: "acknowledgeReferrerByKey";
83
+ readonly type: "function";
84
+ readonly stateMutability: "nonpayable";
85
+ readonly inputs: readonly [{
86
+ readonly type: "string";
87
+ readonly name: "key";
88
+ }, {
89
+ readonly type: "string";
90
+ readonly name: "referrerCode";
91
+ }];
92
+ readonly outputs: readonly [];
93
+ }, {
94
+ readonly name: "getCostOfReferral";
95
+ readonly type: "function";
96
+ readonly stateMutability: "view";
97
+ readonly inputs: readonly [{
98
+ readonly type: "string";
99
+ readonly name: "key";
100
+ }];
101
+ readonly outputs: readonly [{
102
+ readonly type: "uint256";
103
+ }];
104
+ }, {
105
+ readonly name: "getPaymentToken";
106
+ readonly type: "function";
107
+ readonly stateMutability: "view";
108
+ readonly inputs: readonly [{
109
+ readonly type: "string";
110
+ readonly name: "key";
111
+ }];
112
+ readonly outputs: readonly [{
113
+ readonly type: "address";
114
+ }];
115
+ }, {
116
+ readonly name: "getReferrerStatusByKey";
117
+ readonly type: "function";
118
+ readonly stateMutability: "view";
119
+ readonly inputs: readonly [{
120
+ readonly type: "string";
121
+ readonly name: "key";
122
+ }, {
123
+ readonly type: "address";
124
+ readonly name: "referrer";
125
+ }];
126
+ readonly outputs: readonly [{
127
+ readonly type: "uint8";
128
+ }];
129
+ }, {
130
+ readonly name: "requiresAuthorization";
131
+ readonly type: "function";
132
+ readonly stateMutability: "view";
133
+ readonly inputs: readonly [{
134
+ readonly type: "string";
135
+ readonly name: "key";
136
+ }];
137
+ readonly outputs: readonly [{
138
+ readonly type: "bool";
139
+ }];
140
+ }, {
141
+ readonly name: "requiresRefererToBeSet";
142
+ readonly type: "function";
143
+ readonly stateMutability: "view";
144
+ readonly inputs: readonly [{
145
+ readonly type: "string";
146
+ readonly name: "key";
147
+ }];
148
+ readonly outputs: readonly [{
149
+ readonly type: "bool";
150
+ }];
151
+ }, {
152
+ readonly name: "becomeReferrer";
153
+ readonly type: "function";
154
+ readonly stateMutability: "payable";
155
+ readonly inputs: readonly [{
156
+ readonly type: "string";
157
+ readonly name: "key";
158
+ }, {
159
+ readonly type: "string";
160
+ readonly name: "referrerCode";
161
+ }];
162
+ readonly outputs: readonly [];
163
+ }];
164
+ static getReferralContract(chainId: number): "0xF39CC381B91f36238c77f42B9fF4D45376F80E5b" | undefined;
165
+ static isKeyAvailable(key: string, chainId: number): Promise<any>;
166
+ static getReferredUsers(chainId: number, key: string, address: string): Promise<any>;
167
+ static getReferralStatus(chainId: number, key: string, address: string): Promise<boolean>;
168
+ static generateCode(chainId: number, key: string, address: string): string;
169
+ static getCode(chainId: number, key: string, address: string): Promise<any>;
170
+ /**
171
+ * Get state & transaction for creating a referral code
172
+ * @param chainId of the referral contract
173
+ * @param key of referral
174
+ * @param address of the creator
175
+ */
176
+ static getCodeOrTransaction(chainId: number, key: string, address: string): Promise<{
177
+ code: string;
178
+ referrer: boolean;
179
+ referredUsers: never[];
180
+ transaction: {
181
+ to: string;
182
+ data: `0x${string}`;
183
+ };
184
+ } | {
185
+ code: any;
186
+ referrer: boolean;
187
+ referredUsers: any;
188
+ transaction?: undefined;
189
+ }>;
190
+ /**
191
+ * Checks if code exists in the contracts
192
+ * @param chainId of the referral contract
193
+ * @param key of referral
194
+ * @param code user referral code
195
+ * @returns referrerAddress if code exitst
196
+ */
197
+ static isCodeRegistered(chainId: number, key: string, code: string): Promise<any>;
198
+ /**
199
+ * Get state & transaction for redeeming a referral code
200
+ * @param chainId of the referral contract
201
+ * @param key of referral
202
+ * @param code user referral code
203
+ */
204
+ static getReferralTransaction(chainId: number, key: string, code: string): Promise<{
205
+ code: string;
206
+ referrer: any;
207
+ transaction?: undefined;
208
+ } | {
209
+ code: string;
210
+ referrer: any;
211
+ transaction: {
212
+ to: string;
213
+ data: `0x${string}`;
214
+ };
215
+ }>;
216
+ }
@@ -0,0 +1,170 @@
1
+ import { ChainId, ChainInteractionService } from "@sdk";
2
+ import { decodeFunctionResult, encodeFunctionData, parseAbi, } from "viem";
3
+ export class ReferralService {
4
+ static abi = parseAbi([
5
+ "function getReferralKeys() external view returns (string[] memory)",
6
+ "function getReferrerStatus(string calldata key, address user) external view returns (bytes32)",
7
+ "function referrerCodeMapping(string key, address user) external view returns (string)",
8
+ "function codeToReferrer(string key, string user) external view returns (address)",
9
+ "function getReferrer(string calldata key, address user) external view returns (address)",
10
+ "function getReferredUsers(string calldata key, address user) external view returns (address[] memory)",
11
+ "function acknowledgeReferrerByKey(string calldata key, string calldata referrerCode) external",
12
+ "function getCostOfReferral(string calldata key) external view returns (uint256)",
13
+ "function getPaymentToken(string calldata key) external view returns (address)",
14
+ "function getReferrerStatusByKey(string calldata key, address referrer) external view returns (uint8)",
15
+ "function requiresAuthorization(string calldata key) external view returns (bool)",
16
+ "function requiresRefererToBeSet(string calldata key) external view returns (bool)",
17
+ "function becomeReferrer(string calldata key, string calldata referrerCode) external payable",
18
+ ]);
19
+ static getReferralContract(chainId) {
20
+ if (chainId === ChainId.ETHERLINK)
21
+ return "0xF39CC381B91f36238c77f42B9fF4D45376F80E5b";
22
+ return;
23
+ }
24
+ /**
25
+ * Makes an on-chain call to the referral contract
26
+ * @param chainId
27
+ * @param functionName
28
+ * @param args
29
+ * @returns
30
+ */
31
+ static async #call(chainId, functionName, args) {
32
+ const referralContractAddress = ReferralService.getReferralContract(chainId);
33
+ if (!referralContractAddress)
34
+ throw new Error(`Referral contract not deployed on chain ${chainId}`);
35
+ return await ChainInteractionService(chainId).fetchAndDecode({
36
+ target: referralContractAddress,
37
+ allowFailure: true,
38
+ callData: encodeFunctionData({
39
+ abi: ReferralService.abi,
40
+ functionName,
41
+ args,
42
+ }),
43
+ }, (r) => decodeFunctionResult({
44
+ abi: ReferralService.abi,
45
+ functionName,
46
+ data: r?.returnData,
47
+ }));
48
+ }
49
+ static async isKeyAvailable(key, chainId) {
50
+ const referralKeys = await ReferralService.#call(chainId, "getReferralKeys", []);
51
+ return referralKeys.includes(key);
52
+ }
53
+ static async getReferredUsers(chainId, key, address) {
54
+ const isReferralKeyAvailable = ReferralService.isKeyAvailable(key, chainId);
55
+ if (!isReferralKeyAvailable)
56
+ throw new Error(`Referral key ${key} not available on ${chainId}`);
57
+ return await ReferralService.#call(chainId, "getReferredUsers", [key, address]);
58
+ }
59
+ static async getReferralStatus(chainId, key, address) {
60
+ const referralContractAddress = ReferralService.getReferralContract(chainId);
61
+ const isReferralKeyAvailable = ReferralService.isKeyAvailable(key, chainId);
62
+ if (!referralContractAddress)
63
+ throw new Error(`Referral contract not deployed on chain ${chainId}`);
64
+ if (!isReferralKeyAvailable)
65
+ throw new Error(`Referral key ${key} not available on ${chainId}`);
66
+ const shouldCheckStatus = await ReferralService.#call(chainId, "requiresAuthorization", [key]);
67
+ if (!shouldCheckStatus)
68
+ return true;
69
+ const referralStatus = await ReferralService.#call(chainId, "getReferrerStatusByKey", [
70
+ key,
71
+ address,
72
+ ]);
73
+ return referralStatus === 1;
74
+ }
75
+ static generateCode(chainId, key, address) {
76
+ return Bun.hash([chainId, key, address].join("-")).toString().slice(0, 12);
77
+ }
78
+ static async getCode(chainId, key, address) {
79
+ const referralContractAddress = ReferralService.getReferralContract(chainId);
80
+ if (!referralContractAddress)
81
+ throw new Error(`Referral contract not deployed on chain ${chainId}`);
82
+ const code = await ReferralService.#call(chainId, "referrerCodeMapping", [key, address]);
83
+ return code === "" ? undefined : code;
84
+ }
85
+ /**
86
+ * Get state & transaction for creating a referral code
87
+ * @param chainId of the referral contract
88
+ * @param key of referral
89
+ * @param address of the creator
90
+ */
91
+ static async getCodeOrTransaction(chainId, key, address) {
92
+ const referralContractAddress = ReferralService.getReferralContract(chainId);
93
+ const isReferralKeyAvailable = ReferralService.isKeyAvailable(key, chainId);
94
+ if (!referralContractAddress)
95
+ throw new Error(`Referral contract not deployed on chain ${chainId}`);
96
+ if (!isReferralKeyAvailable)
97
+ throw new Error(`Referral key ${key} not available on ${chainId}`);
98
+ const contractCode = await ReferralService.getCode(chainId, key, address);
99
+ if (!contractCode) {
100
+ const code = ReferralService.generateCode(chainId, key, address);
101
+ return {
102
+ code,
103
+ referrer: false,
104
+ referredUsers: [],
105
+ transaction: {
106
+ to: referralContractAddress,
107
+ data: encodeFunctionData({
108
+ abi: ReferralService.abi,
109
+ functionName: "becomeReferrer",
110
+ args: [key, code],
111
+ }),
112
+ },
113
+ };
114
+ }
115
+ const code = await ReferralService.getCode(chainId, key, address);
116
+ const referredUsers = await ReferralService.getReferredUsers(chainId, key, address);
117
+ return {
118
+ code,
119
+ referrer: true,
120
+ referredUsers,
121
+ };
122
+ }
123
+ /**
124
+ * Checks if code exists in the contracts
125
+ * @param chainId of the referral contract
126
+ * @param key of referral
127
+ * @param code user referral code
128
+ * @returns referrerAddress if code exitst
129
+ */
130
+ static async isCodeRegistered(chainId, key, code) {
131
+ const referralContractAddress = ReferralService.getReferralContract(chainId);
132
+ if (!referralContractAddress)
133
+ throw new Error(`Referral contract not deployed on chain ${chainId}`);
134
+ const referrerAddress = await ReferralService.#call(chainId, "codeToReferrer", [key, code]);
135
+ return referrerAddress === "" ? undefined : referrerAddress;
136
+ }
137
+ /**
138
+ * Get state & transaction for redeeming a referral code
139
+ * @param chainId of the referral contract
140
+ * @param key of referral
141
+ * @param code user referral code
142
+ */
143
+ static async getReferralTransaction(chainId, key, code) {
144
+ const referralContractAddress = ReferralService.getReferralContract(chainId);
145
+ const isReferralKeyAvailable = ReferralService.isKeyAvailable(key, chainId);
146
+ if (!referralContractAddress)
147
+ throw new Error(`Referral contract not deployed on chain ${chainId}`);
148
+ if (!isReferralKeyAvailable)
149
+ throw new Error(`Referral key ${key} not available on ${chainId}`);
150
+ const referrerAddress = await ReferralService.isCodeRegistered(chainId, key, code);
151
+ if (!referrerAddress) {
152
+ return {
153
+ code,
154
+ referrer: referrerAddress,
155
+ };
156
+ }
157
+ return {
158
+ code,
159
+ referrer: referrerAddress,
160
+ transaction: {
161
+ to: referralContractAddress,
162
+ data: encodeFunctionData({
163
+ abi: ReferralService.abi,
164
+ functionName: "acknowledgeReferrerByKey",
165
+ args: [key, code],
166
+ }),
167
+ },
168
+ };
169
+ }
170
+ }
@@ -3789,6 +3789,68 @@ export declare const v4: Elysia<"/v4", false, {
3789
3789
  };
3790
3790
  };
3791
3791
  };
3792
+ } & {
3793
+ v4: {
3794
+ referral: {
3795
+ code: {
3796
+ get: {
3797
+ body: unknown;
3798
+ params: {};
3799
+ query: {
3800
+ chainId: number;
3801
+ address: string;
3802
+ referralKey: string;
3803
+ };
3804
+ headers: unknown;
3805
+ response: {
3806
+ 200: {
3807
+ code: string;
3808
+ referrer: boolean;
3809
+ referredUsers: never[];
3810
+ transaction: {
3811
+ to: string;
3812
+ data: `0x${string}`;
3813
+ };
3814
+ } | {
3815
+ code: any;
3816
+ referrer: boolean;
3817
+ referredUsers: any;
3818
+ transaction?: undefined;
3819
+ };
3820
+ };
3821
+ };
3822
+ };
3823
+ };
3824
+ } & {
3825
+ referral: {
3826
+ redeem: {
3827
+ get: {
3828
+ body: unknown;
3829
+ params: {};
3830
+ query: {
3831
+ code: string;
3832
+ chainId: number;
3833
+ referralKey: string;
3834
+ };
3835
+ headers: unknown;
3836
+ response: {
3837
+ 200: {
3838
+ code: string;
3839
+ referrer: any;
3840
+ transaction?: undefined;
3841
+ } | {
3842
+ code: string;
3843
+ referrer: any;
3844
+ transaction: {
3845
+ to: string;
3846
+ data: `0x${string}`;
3847
+ };
3848
+ };
3849
+ };
3850
+ };
3851
+ };
3852
+ };
3853
+ };
3792
3854
  }, {
3793
3855
  derive: {};
3794
3856
  resolve: {};
@@ -27,6 +27,7 @@ import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
27
27
  import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-node";
28
28
  import { PrismaInstrumentation } from "@prisma/instrumentation";
29
29
  import Elysia from "elysia";
30
+ import { ReferralController } from "./referral/referral.controller";
30
31
  // ─── V4 Router ───────────────────────────────────────────────────────────────
31
32
  export const v4 = new Elysia({ tags: ["v4"], prefix: "/v4" })
32
33
  // ─── OpenTelemetry ───────────────────────────────────────────────────
@@ -71,4 +72,5 @@ export const v4 = new Elysia({ tags: ["v4"], prefix: "/v4" })
71
72
  .use(ProgramPayloadController)
72
73
  .use(BoostController)
73
74
  .use(ComputedValueController)
74
- .use(CreatorController);
75
+ .use(CreatorController)
76
+ .use(ReferralController);