@towns-labs/app-framework 4.0.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/README.md +147 -0
- package/dist/app.d.ts +680 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +2324 -0
- package/dist/app.js.map +1 -0
- package/dist/app.test.d.ts +2 -0
- package/dist/app.test.d.ts.map +1 -0
- package/dist/app.test.js +2070 -0
- package/dist/app.test.js.map +1 -0
- package/dist/identity-types.d.ts +43 -0
- package/dist/identity-types.d.ts.map +1 -0
- package/dist/identity-types.js +2 -0
- package/dist/identity-types.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/modules/eventDedup.d.ts +73 -0
- package/dist/modules/eventDedup.d.ts.map +1 -0
- package/dist/modules/eventDedup.js +105 -0
- package/dist/modules/eventDedup.js.map +1 -0
- package/dist/modules/eventDedup.test.d.ts +2 -0
- package/dist/modules/eventDedup.test.d.ts.map +1 -0
- package/dist/modules/eventDedup.test.js +222 -0
- package/dist/modules/eventDedup.test.js.map +1 -0
- package/dist/modules/interaction-api.d.ts +101 -0
- package/dist/modules/interaction-api.d.ts.map +1 -0
- package/dist/modules/interaction-api.js +213 -0
- package/dist/modules/interaction-api.js.map +1 -0
- package/dist/modules/payments.d.ts +89 -0
- package/dist/modules/payments.d.ts.map +1 -0
- package/dist/modules/payments.js +139 -0
- package/dist/modules/payments.js.map +1 -0
- package/dist/modules/user.d.ts +17 -0
- package/dist/modules/user.d.ts.map +1 -0
- package/dist/modules/user.js +54 -0
- package/dist/modules/user.js.map +1 -0
- package/dist/snapshot-getter.d.ts +21 -0
- package/dist/snapshot-getter.d.ts.map +1 -0
- package/dist/snapshot-getter.js +27 -0
- package/dist/snapshot-getter.js.map +1 -0
- package/package.json +66 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import type { Address, Hex } from 'viem';
|
|
2
|
+
import type { AgentHandler, BasePayload } from '../app';
|
|
3
|
+
import type { Price, RouteConfig } from 'x402/types';
|
|
4
|
+
export declare const USDC_ADDRESSES: Record<number, Address>;
|
|
5
|
+
export interface PendingPayment {
|
|
6
|
+
command: string;
|
|
7
|
+
channelId: string;
|
|
8
|
+
userId: string;
|
|
9
|
+
/** The eventId of the interaction request message (to delete after signing) */
|
|
10
|
+
interactionEventId: string;
|
|
11
|
+
event: BasePayload & {
|
|
12
|
+
command: string;
|
|
13
|
+
args: string[];
|
|
14
|
+
mentions: any[];
|
|
15
|
+
replyId: string | undefined;
|
|
16
|
+
threadId: string | undefined;
|
|
17
|
+
};
|
|
18
|
+
params: TransferAuthorizationParams;
|
|
19
|
+
}
|
|
20
|
+
export declare function chainIdToNetwork(chainId: number): 'base' | 'base-sepolia';
|
|
21
|
+
export declare function getUsdcAddress(chainId: number): Address;
|
|
22
|
+
export interface TransferAuthorizationParams {
|
|
23
|
+
from: Address;
|
|
24
|
+
to: Address;
|
|
25
|
+
value: bigint;
|
|
26
|
+
validAfter: bigint;
|
|
27
|
+
validBefore: bigint;
|
|
28
|
+
nonce: Hex;
|
|
29
|
+
chainId: number;
|
|
30
|
+
verifyingContract: Address;
|
|
31
|
+
}
|
|
32
|
+
export interface TypedData {
|
|
33
|
+
types: {
|
|
34
|
+
[key: string]: Array<{
|
|
35
|
+
name: string;
|
|
36
|
+
type: string;
|
|
37
|
+
}>;
|
|
38
|
+
};
|
|
39
|
+
domain: {
|
|
40
|
+
name: string;
|
|
41
|
+
version: string;
|
|
42
|
+
chainId: number;
|
|
43
|
+
verifyingContract: Address;
|
|
44
|
+
};
|
|
45
|
+
primaryType: string;
|
|
46
|
+
message: {
|
|
47
|
+
[key: string]: any;
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Generate a unique nonce for USDC authorization
|
|
52
|
+
* Uses crypto-safe random bytes
|
|
53
|
+
*/
|
|
54
|
+
export declare function generateNonce(): Hex;
|
|
55
|
+
/**
|
|
56
|
+
* Get validity window for authorization
|
|
57
|
+
* validAfter: current timestamp
|
|
58
|
+
* validBefore: current timestamp + 1 hour
|
|
59
|
+
*/
|
|
60
|
+
export declare function getValidityWindow(): {
|
|
61
|
+
validAfter: bigint;
|
|
62
|
+
validBefore: bigint;
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Build EIP-712 typed data for USDC transferWithAuthorization signature request
|
|
66
|
+
* Synchronous version for sending to client - no contract calls needed
|
|
67
|
+
*/
|
|
68
|
+
export declare function buildTransferAuthorizationTypedDataForSigning(params: TransferAuthorizationParams): TypedData;
|
|
69
|
+
/**
|
|
70
|
+
* Simplified payment request builder
|
|
71
|
+
* Returns all data needed to track and verify the payment
|
|
72
|
+
*/
|
|
73
|
+
export declare function createPaymentRequest(handler: AgentHandler, event: BasePayload, chainId: number, fromAddress: Address, recipientAddress: Address, paymentConfig: RouteConfig, command: string): Promise<{
|
|
74
|
+
signatureId: string;
|
|
75
|
+
params: TransferAuthorizationParams;
|
|
76
|
+
eventId: string;
|
|
77
|
+
}>;
|
|
78
|
+
/**
|
|
79
|
+
* Parses a USDC price to atomic units (6 decimals).
|
|
80
|
+
* Handles dollar signs, commas, and decimal amounts.
|
|
81
|
+
* Only string and number inputs are supported.
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* parseUSDCPrice("$1.00") // 1000000n
|
|
85
|
+
* parseUSDCPrice(1.50) // 1500000n
|
|
86
|
+
* parseUSDCPrice("$1,000.00") // 1000000000n
|
|
87
|
+
*/
|
|
88
|
+
export declare function parseUSDCPrice(price: Price): bigint;
|
|
89
|
+
//# sourceMappingURL=payments.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payments.d.ts","sourceRoot":"","sources":["../../src/modules/payments.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,MAAM,CAAA;AAGxC,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAA;AACvD,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAEpD,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAGlD,CAAA;AAED,MAAM,WAAW,cAAc;IAC3B,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;IACd,+EAA+E;IAC/E,kBAAkB,EAAE,MAAM,CAAA;IAC1B,KAAK,EAAE,WAAW,GAAG;QACjB,OAAO,EAAE,MAAM,CAAA;QACf,IAAI,EAAE,MAAM,EAAE,CAAA;QACd,QAAQ,EAAE,GAAG,EAAE,CAAA;QACf,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;QAC3B,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAA;KAC/B,CAAA;IACD,MAAM,EAAE,2BAA2B,CAAA;CACtC;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,cAAc,CASzE;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAMvD;AAGD,MAAM,WAAW,2BAA2B;IACxC,IAAI,EAAE,OAAO,CAAA;IACb,EAAE,EAAE,OAAO,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;IACnB,KAAK,EAAE,GAAG,CAAA;IACV,OAAO,EAAE,MAAM,CAAA;IACf,iBAAiB,EAAE,OAAO,CAAA;CAC7B;AAED,MAAM,WAAW,SAAS;IACtB,KAAK,EAAE;QACH,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KACvD,CAAA;IACD,MAAM,EAAE;QACJ,IAAI,EAAE,MAAM,CAAA;QACZ,OAAO,EAAE,MAAM,CAAA;QACf,OAAO,EAAE,MAAM,CAAA;QACf,iBAAiB,EAAE,OAAO,CAAA;KAC7B,CAAA;IACD,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE;QACL,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KACrB,CAAA;CACJ;AAED;;;GAGG;AACH,wBAAgB,aAAa,IAAI,GAAG,CAGnC;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,IAAI;IACjC,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;CACtB,CAMA;AAED;;;GAGG;AACH,wBAAgB,6CAA6C,CACzD,MAAM,EAAE,2BAA2B,GACpC,SAAS,CA4BX;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CACtC,OAAO,EAAE,YAAY,EACrB,KAAK,EAAE,WAAW,EAClB,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,OAAO,EACpB,gBAAgB,EAAE,OAAO,EACzB,aAAa,EAAE,WAAW,EAC1B,OAAO,EAAE,MAAM;;;;GAyClB;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAkBnD"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { keccak256 } from 'viem';
|
|
2
|
+
import { baseSepolia, base } from 'viem/chains';
|
|
3
|
+
export const USDC_ADDRESSES = {
|
|
4
|
+
[baseSepolia.id]: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',
|
|
5
|
+
[base.id]: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
|
|
6
|
+
};
|
|
7
|
+
export function chainIdToNetwork(chainId) {
|
|
8
|
+
switch (chainId) {
|
|
9
|
+
case base.id:
|
|
10
|
+
return 'base';
|
|
11
|
+
case baseSepolia.id:
|
|
12
|
+
return 'base-sepolia';
|
|
13
|
+
default:
|
|
14
|
+
throw new Error(`Unsupported chain ID: ${chainId}`);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export function getUsdcAddress(chainId) {
|
|
18
|
+
const address = USDC_ADDRESSES[chainId];
|
|
19
|
+
if (!address) {
|
|
20
|
+
throw new Error(`USDC address not found for chain ID: ${chainId}`);
|
|
21
|
+
}
|
|
22
|
+
return address;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Generate a unique nonce for USDC authorization
|
|
26
|
+
* Uses crypto-safe random bytes
|
|
27
|
+
*/
|
|
28
|
+
export function generateNonce() {
|
|
29
|
+
const randomBytes = crypto.getRandomValues(new Uint8Array(32));
|
|
30
|
+
return keccak256(randomBytes);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Get validity window for authorization
|
|
34
|
+
* validAfter: current timestamp
|
|
35
|
+
* validBefore: current timestamp + 1 hour
|
|
36
|
+
*/
|
|
37
|
+
export function getValidityWindow() {
|
|
38
|
+
const now = BigInt(Math.floor(Date.now() / 1000));
|
|
39
|
+
return {
|
|
40
|
+
validAfter: now,
|
|
41
|
+
validBefore: now + 3600n, // 1 hour
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Build EIP-712 typed data for USDC transferWithAuthorization signature request
|
|
46
|
+
* Synchronous version for sending to client - no contract calls needed
|
|
47
|
+
*/
|
|
48
|
+
export function buildTransferAuthorizationTypedDataForSigning(params) {
|
|
49
|
+
return {
|
|
50
|
+
types: {
|
|
51
|
+
TransferWithAuthorization: [
|
|
52
|
+
{ name: 'from', type: 'address' },
|
|
53
|
+
{ name: 'to', type: 'address' },
|
|
54
|
+
{ name: 'value', type: 'uint256' },
|
|
55
|
+
{ name: 'validAfter', type: 'uint256' },
|
|
56
|
+
{ name: 'validBefore', type: 'uint256' },
|
|
57
|
+
{ name: 'nonce', type: 'bytes32' },
|
|
58
|
+
],
|
|
59
|
+
},
|
|
60
|
+
domain: {
|
|
61
|
+
name: 'USDC',
|
|
62
|
+
version: '2',
|
|
63
|
+
chainId: params.chainId,
|
|
64
|
+
verifyingContract: params.verifyingContract,
|
|
65
|
+
},
|
|
66
|
+
primaryType: 'TransferWithAuthorization',
|
|
67
|
+
message: {
|
|
68
|
+
from: params.from,
|
|
69
|
+
to: params.to,
|
|
70
|
+
value: params.value.toString(),
|
|
71
|
+
validAfter: params.validAfter.toString(),
|
|
72
|
+
validBefore: params.validBefore.toString(),
|
|
73
|
+
nonce: params.nonce,
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Simplified payment request builder
|
|
79
|
+
* Returns all data needed to track and verify the payment
|
|
80
|
+
*/
|
|
81
|
+
export async function createPaymentRequest(handler, event, chainId, fromAddress, recipientAddress, paymentConfig, command) {
|
|
82
|
+
const usdcAddr = getUsdcAddress(chainId);
|
|
83
|
+
const nonce = generateNonce();
|
|
84
|
+
const { validAfter, validBefore } = getValidityWindow();
|
|
85
|
+
const value = parseUSDCPrice(paymentConfig.price);
|
|
86
|
+
const params = {
|
|
87
|
+
from: fromAddress,
|
|
88
|
+
to: recipientAddress,
|
|
89
|
+
value: value,
|
|
90
|
+
validAfter,
|
|
91
|
+
validBefore,
|
|
92
|
+
nonce,
|
|
93
|
+
chainId: chainId,
|
|
94
|
+
verifyingContract: usdcAddr,
|
|
95
|
+
};
|
|
96
|
+
const typedData = buildTransferAuthorizationTypedDataForSigning(params);
|
|
97
|
+
// Format price for display
|
|
98
|
+
const priceDisplay = typeof paymentConfig.price === 'string' || typeof paymentConfig.price === 'number'
|
|
99
|
+
? String(paymentConfig.price)
|
|
100
|
+
: JSON.stringify(paymentConfig.price);
|
|
101
|
+
const result = await handler.sendInteractionRequest(event.channelId, {
|
|
102
|
+
type: 'signature',
|
|
103
|
+
method: 'typed_data',
|
|
104
|
+
data: JSON.stringify(typedData),
|
|
105
|
+
chainId: params.chainId.toString(),
|
|
106
|
+
signerWallet: fromAddress,
|
|
107
|
+
title: `Payment Required for /${command} • ${priceDisplay} USDC`,
|
|
108
|
+
subtitle: `Sign to authorize payment`,
|
|
109
|
+
});
|
|
110
|
+
return {
|
|
111
|
+
signatureId: result.requestId,
|
|
112
|
+
params,
|
|
113
|
+
eventId: result.eventId,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Parses a USDC price to atomic units (6 decimals).
|
|
118
|
+
* Handles dollar signs, commas, and decimal amounts.
|
|
119
|
+
* Only string and number inputs are supported.
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* parseUSDCPrice("$1.00") // 1000000n
|
|
123
|
+
* parseUSDCPrice(1.50) // 1500000n
|
|
124
|
+
* parseUSDCPrice("$1,000.00") // 1000000000n
|
|
125
|
+
*/
|
|
126
|
+
export function parseUSDCPrice(price) {
|
|
127
|
+
if (typeof price !== 'string' && typeof price !== 'number') {
|
|
128
|
+
throw new Error(`parseUSDCPrice only supports string or number inputs, got: ${typeof price}`);
|
|
129
|
+
}
|
|
130
|
+
const rawStr = String(price);
|
|
131
|
+
const sanitized = rawStr.replace(/[$,\s]/g, '').trim();
|
|
132
|
+
if (!/^\d+(\.\d{0,6})?$/.test(sanitized)) {
|
|
133
|
+
throw new Error(`Invalid USDC price format: ${JSON.stringify(price)}`);
|
|
134
|
+
}
|
|
135
|
+
const [whole, frac = ''] = sanitized.split('.');
|
|
136
|
+
const paddedFrac = frac.padEnd(6, '0').slice(0, 6);
|
|
137
|
+
return BigInt(whole || '0') * 1000000n + BigInt(paddedFrac);
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=payments.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payments.js","sourceRoot":"","sources":["../../src/modules/payments.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Address } from 'viem';
|
|
2
|
+
import type { AppRegistryRpcClient } from '@towns-labs/sdk';
|
|
3
|
+
export type UserInfo = {
|
|
4
|
+
/** The user's address (0x string) */
|
|
5
|
+
id: Address;
|
|
6
|
+
/** The user's display name from the app registry */
|
|
7
|
+
displayName: string;
|
|
8
|
+
/** The user's username from the app registry */
|
|
9
|
+
username: string;
|
|
10
|
+
};
|
|
11
|
+
export declare class UserInfoCache {
|
|
12
|
+
private cache;
|
|
13
|
+
get(userId: string): UserInfo | undefined;
|
|
14
|
+
set(userId: string, info: UserInfo): void;
|
|
15
|
+
}
|
|
16
|
+
export declare function getUserBulk(userIds: Address[], cache: UserInfoCache, getAppRegistryClient: () => Promise<AppRegistryRpcClient>): Promise<Map<Address, UserInfo | undefined>>;
|
|
17
|
+
//# sourceMappingURL=user.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user.d.ts","sourceRoot":"","sources":["../../src/modules/user.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AACnC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAA;AAG3D,MAAM,MAAM,QAAQ,GAAG;IACnB,qCAAqC;IACrC,EAAE,EAAE,OAAO,CAAA;IACX,oDAAoD;IACpD,WAAW,EAAE,MAAM,CAAA;IACnB,gDAAgD;IAChD,QAAQ,EAAE,MAAM,CAAA;CACnB,CAAA;AASD,qBAAa,aAAa;IACtB,OAAO,CAAC,KAAK,CAAoC;IAEjD,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS;IAUzC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,IAAI;CAM5C;AAED,wBAAsB,WAAW,CAC7B,OAAO,EAAE,OAAO,EAAE,EAClB,KAAK,EAAE,aAAa,EACpB,oBAAoB,EAAE,MAAM,OAAO,CAAC,oBAAoB,CAAC,GAC1D,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,QAAQ,GAAG,SAAS,CAAC,CAAC,CAsC7C"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { addressFromUserId, userIdFromAddress } from '@towns-labs/sdk';
|
|
2
|
+
const USER_INFO_TTL_MS = 5 * 60 * 1000; // 5 minutes
|
|
3
|
+
export class UserInfoCache {
|
|
4
|
+
cache = new Map();
|
|
5
|
+
get(userId) {
|
|
6
|
+
const entry = this.cache.get(userId.toLowerCase());
|
|
7
|
+
if (!entry)
|
|
8
|
+
return undefined;
|
|
9
|
+
if (Date.now() > entry.expiresAt) {
|
|
10
|
+
this.cache.delete(userId.toLowerCase());
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
13
|
+
return entry.value;
|
|
14
|
+
}
|
|
15
|
+
set(userId, info) {
|
|
16
|
+
this.cache.set(userId.toLowerCase(), {
|
|
17
|
+
value: info,
|
|
18
|
+
expiresAt: Date.now() + USER_INFO_TTL_MS,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export async function getUserBulk(userIds, cache, getAppRegistryClient) {
|
|
23
|
+
const looked = userIds.map((id) => [id, cache.get(id)]);
|
|
24
|
+
const uncached = looked.filter(([, v]) => !v).map(([id]) => id);
|
|
25
|
+
const result = new Map(looked.filter(([, v]) => v).map(([id, v]) => [id, v]));
|
|
26
|
+
if (uncached.length === 0)
|
|
27
|
+
return result;
|
|
28
|
+
try {
|
|
29
|
+
const appRegistry = await getAppRegistryClient();
|
|
30
|
+
const response = await appRegistry.getBatchEntityNames({
|
|
31
|
+
entityIds: uncached.map((userId) => addressFromUserId(userId)),
|
|
32
|
+
});
|
|
33
|
+
const found = new Map((response.entities ?? []).map((entity) => {
|
|
34
|
+
const resolvedUserId = userIdFromAddress(entity.entityId);
|
|
35
|
+
const info = {
|
|
36
|
+
id: resolvedUserId,
|
|
37
|
+
displayName: entity.displayName ?? '',
|
|
38
|
+
username: entity.username ?? '',
|
|
39
|
+
};
|
|
40
|
+
cache.set(resolvedUserId, info);
|
|
41
|
+
return [resolvedUserId.toLowerCase(), info];
|
|
42
|
+
}));
|
|
43
|
+
for (const userId of uncached) {
|
|
44
|
+
result.set(userId, found.get(userId.toLowerCase()));
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
for (const userId of uncached) {
|
|
49
|
+
result.set(userId, undefined);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return result;
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=user.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user.js","sourceRoot":"","sources":["../../src/modules/user.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { PlainMessage, Snapshot } from '@towns-labs/proto';
|
|
2
|
+
import type { ParsedStreamResponse, Prettify } from '@towns-labs/sdk';
|
|
3
|
+
type RemoveContent<T extends string> = T extends `${infer Prefix}Content` ? Prefix : T;
|
|
4
|
+
type SnapshotContent = Exclude<Snapshot['content'], {
|
|
5
|
+
case: undefined;
|
|
6
|
+
}>;
|
|
7
|
+
type SnapshotTypeMap = {
|
|
8
|
+
[K in SnapshotContent['case']]: Extract<SnapshotContent, {
|
|
9
|
+
case: K;
|
|
10
|
+
}>['value'];
|
|
11
|
+
};
|
|
12
|
+
type GenerateGetters<SnapshotCase extends keyof SnapshotTypeMap, SnapshotType = PlainMessage<SnapshotTypeMap[SnapshotCase]>> = {
|
|
13
|
+
[Prop in NonNullable<keyof SnapshotType> as `get${Capitalize<RemoveContent<SnapshotCase>>}${Capitalize<string & Prop>}`]: (streamId: string) => Promise<SnapshotType[Prop]>;
|
|
14
|
+
};
|
|
15
|
+
type UnionToIntersection<U> = (U extends any ? (x: U) => void : never) extends (x: infer I) => void ? I : never;
|
|
16
|
+
type GetterFunctions = UnionToIntersection<{
|
|
17
|
+
[K in keyof SnapshotTypeMap]: GenerateGetters<K>;
|
|
18
|
+
}[keyof SnapshotTypeMap]>;
|
|
19
|
+
export declare const SnapshotGetter: (getStream: (streamId: string) => Promise<ParsedStreamResponse>) => Prettify<GetterFunctions>;
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=snapshot-getter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot-getter.d.ts","sourceRoot":"","sources":["../src/snapshot-getter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAoB,MAAM,mBAAmB,CAAA;AACjF,OAAO,KAAK,EAAE,oBAAoB,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAIrE,KAAK,aAAa,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,SAAS,GAAG,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,CAAC,CAAA;AAGtF,KAAK,eAAe,GAAG,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC,CAAA;AAGxE,KAAK,eAAe,GAAG;KAClB,CAAC,IAAI,eAAe,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,eAAe,EAAE;QAAE,IAAI,EAAE,CAAC,CAAA;KAAE,CAAC,CAAC,OAAO,CAAC;CACjF,CAAA;AAGD,KAAK,eAAe,CAChB,YAAY,SAAS,MAAM,eAAe,EAC1C,YAAY,GAAG,YAAY,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,IAC1D;KACC,IAAI,IAAI,WAAW,CAChB,MAAM,YAAY,CACrB,IAAI,MAAM,UAAU,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,GAAG,UAAU,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,GAAG,CAC/E,QAAQ,EAAE,MAAM,KACf,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;CACnC,CAAA;AAGD,KAAK,mBAAmB,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,GAAG,GAAG,CAAC,CAAC,EAAE,CAAC,KAAK,IAAI,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,IAAI,GAC7F,CAAC,GACD,KAAK,CAAA;AAGX,KAAK,eAAe,GAAG,mBAAmB,CACtC;KACK,CAAC,IAAI,MAAM,eAAe,GAAG,eAAe,CAAC,CAAC,CAAC;CACnD,CAAC,MAAM,eAAe,CAAC,CAC3B,CAAA;AAsBD,eAAO,MAAM,cAAc,GAAI,WAAW,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,oBAAoB,CAAC,KAyBpF,QAAQ,CAAC,eAAe,CAAC,CAAA"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const getFromSnapshot = (getStream) => async (streamId, snapshotCase, propertyKey) => {
|
|
2
|
+
const stream = await getStream(streamId);
|
|
3
|
+
if (stream.snapshot.content.case === snapshotCase) {
|
|
4
|
+
const snapshotValue = stream.snapshot.content.value;
|
|
5
|
+
return snapshotValue[propertyKey];
|
|
6
|
+
}
|
|
7
|
+
return undefined;
|
|
8
|
+
};
|
|
9
|
+
export const SnapshotGetter = (getStream) => new Proxy({}, {
|
|
10
|
+
get(_target, prop) {
|
|
11
|
+
return async (streamId) => {
|
|
12
|
+
// Parse the getter name to extract snapshot type and property
|
|
13
|
+
const propName = String(prop);
|
|
14
|
+
// Match pattern like getSpaceInception, getUserMemberships, etc.
|
|
15
|
+
const match = propName.match(/^get([A-Z][a-z]+)([A-Z][a-zA-Z]+)$/);
|
|
16
|
+
if (!match) {
|
|
17
|
+
throw new Error(`Invalid getter name: ${propName}`);
|
|
18
|
+
}
|
|
19
|
+
const [, snapshotType, propertyName] = match;
|
|
20
|
+
const snapshotCase = `${snapshotType.toLowerCase()}Content`;
|
|
21
|
+
const property = (propertyName.charAt(0).toLowerCase() +
|
|
22
|
+
propertyName.slice(1));
|
|
23
|
+
return getFromSnapshot(getStream)(streamId, snapshotCase, property);
|
|
24
|
+
};
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
//# sourceMappingURL=snapshot-getter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot-getter.js","sourceRoot":"","sources":["../src/snapshot-getter.ts"],"names":[],"mappings":"AA4CA,MAAM,eAAe,GACjB,CAAC,SAA8D,EAAE,EAAE,CACnE,KAAK,EACD,QAAgB,EAChB,YAAmB,EACnB,WAAiB,EACqC,EAAE;IACxD,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,CAAA;IACxC,IAAI,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;QAChD,MAAM,aAAa,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAoC,CAAA;QAClF,OAAO,aAAa,CAAC,WAAW,CAAC,CAAA;IACrC,CAAC;IACD,OAAO,SAAS,CAAA;AACpB,CAAC,CAAA;AAEL,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,SAA8D,EAAE,EAAE,CAC7F,IAAI,KAAK,CACL,EAAE,EACF;IACI,GAAG,CAAC,OAAO,EAAE,IAAY;QACrB,OAAO,KAAK,EAAE,QAAgB,EAAE,EAAE;YAC9B,8DAA8D;YAC9D,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,CAAA;YAE7B,iEAAiE;YACjE,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAA;YAClE,IAAI,CAAC,KAAK,EAAE,CAAC;gBACT,MAAM,IAAI,KAAK,CAAC,wBAAwB,QAAQ,EAAE,CAAC,CAAA;YACvD,CAAC;YAED,MAAM,CAAC,EAAE,YAAY,EAAE,YAAY,CAAC,GAAG,KAAK,CAAA;YAC5C,MAAM,YAAY,GACd,GAAG,YAAY,CAAC,WAAW,EAAE,SAAkC,CAAA;YACnE,MAAM,QAAQ,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;gBAClD,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAoD,CAAA;YAE7E,OAAO,eAAe,CAAC,SAAS,CAAC,CAAC,QAAQ,EAAE,YAAY,EAAE,QAAQ,CAAC,CAAA;QACvE,CAAC,CAAA;IACL,CAAC;CACJ,CACyB,CAAA"}
|
package/package.json
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@towns-labs/app-framework",
|
|
3
|
+
"version": "4.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"clean": "rm -rf dist",
|
|
10
|
+
"lint": "eslint --format unix ./src --max-warnings=0",
|
|
11
|
+
"lint:fix": "bun run lint --fix",
|
|
12
|
+
"test": "vitest run",
|
|
13
|
+
"test:ci": "vitest run --silent=passed-only",
|
|
14
|
+
"test:watch": "vitest --watch",
|
|
15
|
+
"typecheck": "tsc --noEmit",
|
|
16
|
+
"watch": "tsc --watch"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@bufbuild/protobuf": "^2.9.0",
|
|
20
|
+
"@connectrpc/connect-node": "^2.1.0",
|
|
21
|
+
"@standard-schema/spec": "^1.0.0-beta.9",
|
|
22
|
+
"@towns-labs/encryption": "^4.0.0",
|
|
23
|
+
"@towns-labs/proto": "^4.0.0",
|
|
24
|
+
"@towns-labs/sdk": "^4.0.0",
|
|
25
|
+
"@towns-labs/sdk-crypto": "^4.0.0",
|
|
26
|
+
"@towns-labs/utils": "^4.0.0",
|
|
27
|
+
"@towns-labs/web3": "^4.0.0",
|
|
28
|
+
"ethers": "^5.8.0",
|
|
29
|
+
"image-size": "^2.0.2",
|
|
30
|
+
"jsonwebtoken": "^9.0.2",
|
|
31
|
+
"nanoevents": "^9.1.0",
|
|
32
|
+
"superjson": "^2.2.2",
|
|
33
|
+
"x402": "^0.7.3"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@hono/node-server": "^1.19.9",
|
|
37
|
+
"@towns-labs/contracts": "^4.0.0",
|
|
38
|
+
"@towns-labs/relayer-client": "^4.0.0",
|
|
39
|
+
"@types/jsonwebtoken": "^9.0.9",
|
|
40
|
+
"@types/node": "^20.14.8",
|
|
41
|
+
"@typescript-eslint/eslint-plugin": "^8.29.0",
|
|
42
|
+
"@typescript-eslint/parser": "^8.29.0",
|
|
43
|
+
"eslint": "^8.57.1",
|
|
44
|
+
"eslint-import-resolver-typescript": "^4.3.2",
|
|
45
|
+
"eslint-plugin-import-x": "^4.10.2",
|
|
46
|
+
"eslint-plugin-tsdoc": "^0.3.0",
|
|
47
|
+
"fake-indexeddb": "^6.0.1",
|
|
48
|
+
"hono": "^4.11.7",
|
|
49
|
+
"nanoid": "^4.0.0",
|
|
50
|
+
"typescript": "~5.8.3",
|
|
51
|
+
"viem": "2.45.1",
|
|
52
|
+
"vitest": "^3.2.3",
|
|
53
|
+
"zod": "^4.3.6"
|
|
54
|
+
},
|
|
55
|
+
"files": [
|
|
56
|
+
"/dist",
|
|
57
|
+
"package.json"
|
|
58
|
+
],
|
|
59
|
+
"peerDependencies": {
|
|
60
|
+
"hono": ">=4",
|
|
61
|
+
"viem": "2.x"
|
|
62
|
+
},
|
|
63
|
+
"publishConfig": {
|
|
64
|
+
"access": "public"
|
|
65
|
+
}
|
|
66
|
+
}
|