@formo/analytics 1.27.0 → 1.28.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/dist/cjs/src/FormoAnalytics.d.ts +69 -12
- package/dist/cjs/src/FormoAnalytics.js +273 -147
- package/dist/cjs/src/event/EventFactory.d.ts +10 -2
- package/dist/cjs/src/event/EventFactory.js +32 -21
- package/dist/cjs/src/index.d.ts +4 -0
- package/dist/cjs/src/index.js +6 -0
- package/dist/cjs/src/privy/index.d.ts +9 -0
- package/dist/cjs/src/privy/index.js +12 -0
- package/dist/cjs/src/privy/types.d.ts +175 -0
- package/dist/cjs/src/privy/types.js +12 -0
- package/dist/cjs/src/privy/utils.d.ts +32 -0
- package/dist/cjs/src/privy/utils.js +188 -0
- package/dist/cjs/src/session/index.js +2 -1
- package/dist/cjs/src/solana/SolanaAdapter.d.ts +211 -0
- package/dist/cjs/src/solana/SolanaAdapter.js +975 -0
- package/dist/cjs/src/solana/SolanaManager.d.ts +24 -0
- package/dist/cjs/src/solana/SolanaManager.js +80 -0
- package/dist/cjs/src/solana/address.d.ts +72 -0
- package/dist/cjs/src/solana/address.js +176 -0
- package/dist/cjs/src/solana/index.d.ts +13 -0
- package/dist/cjs/src/solana/index.js +32 -0
- package/dist/cjs/src/solana/types.d.ts +206 -0
- package/dist/cjs/src/solana/types.js +80 -0
- package/dist/cjs/src/types/base.d.ts +17 -0
- package/dist/cjs/src/types/events.d.ts +4 -3
- package/dist/cjs/src/utils/address.d.ts +21 -0
- package/dist/cjs/src/utils/address.js +48 -1
- package/dist/cjs/src/utils/builderCode.d.ts +30 -0
- package/dist/cjs/src/utils/builderCode.js +143 -0
- package/dist/cjs/src/utils/index.d.ts +1 -0
- package/dist/cjs/src/utils/index.js +1 -0
- package/dist/cjs/src/version.d.ts +1 -1
- package/dist/cjs/src/version.js +1 -1
- package/dist/cjs/src/wagmi/WagmiEventHandler.js +13 -15
- package/dist/cjs/src/wagmi/utils.d.ts +5 -0
- package/dist/cjs/src/wagmi/utils.js +20 -0
- package/dist/esm/src/FormoAnalytics.d.ts +69 -12
- package/dist/esm/src/FormoAnalytics.js +274 -148
- package/dist/esm/src/event/EventFactory.d.ts +10 -2
- package/dist/esm/src/event/EventFactory.js +34 -23
- package/dist/esm/src/index.d.ts +4 -0
- package/dist/esm/src/index.js +3 -0
- package/dist/esm/src/privy/index.d.ts +9 -0
- package/dist/esm/src/privy/index.js +8 -0
- package/dist/esm/src/privy/types.d.ts +175 -0
- package/dist/esm/src/privy/types.js +11 -0
- package/dist/esm/src/privy/utils.d.ts +32 -0
- package/dist/esm/src/privy/utils.js +185 -0
- package/dist/esm/src/session/index.js +2 -1
- package/dist/esm/src/solana/SolanaAdapter.d.ts +211 -0
- package/dist/esm/src/solana/SolanaAdapter.js +972 -0
- package/dist/esm/src/solana/SolanaManager.d.ts +24 -0
- package/dist/esm/src/solana/SolanaManager.js +77 -0
- package/dist/esm/src/solana/address.d.ts +72 -0
- package/dist/esm/src/solana/address.js +167 -0
- package/dist/esm/src/solana/index.d.ts +13 -0
- package/dist/esm/src/solana/index.js +13 -0
- package/dist/esm/src/solana/types.d.ts +206 -0
- package/dist/esm/src/solana/types.js +74 -0
- package/dist/esm/src/types/base.d.ts +17 -0
- package/dist/esm/src/types/events.d.ts +4 -3
- package/dist/esm/src/utils/address.d.ts +21 -0
- package/dist/esm/src/utils/address.js +45 -0
- package/dist/esm/src/utils/builderCode.d.ts +30 -0
- package/dist/esm/src/utils/builderCode.js +140 -0
- package/dist/esm/src/utils/index.d.ts +1 -0
- package/dist/esm/src/utils/index.js +1 -0
- package/dist/esm/src/version.d.ts +1 -1
- package/dist/esm/src/version.js +1 -1
- package/dist/esm/src/wagmi/WagmiEventHandler.js +14 -16
- package/dist/esm/src/wagmi/utils.d.ts +5 -0
- package/dist/esm/src/wagmi/utils.js +19 -0
- package/dist/index.umd.min.js +1 -1
- package/package.json +15 -3
|
@@ -2,9 +2,18 @@ import { LogLevel } from "../logger";
|
|
|
2
2
|
import { IFormoEventContext, IFormoEventProperties, SignatureStatus, TransactionStatus } from "./events";
|
|
3
3
|
import { EIP1193Provider } from "./provider";
|
|
4
4
|
import { ReactNode } from "react";
|
|
5
|
+
import { SolanaOptions } from "../solana/types";
|
|
5
6
|
export type Nullable<T> = T | null;
|
|
6
7
|
export type ChainID = number;
|
|
7
8
|
export type Address = string;
|
|
9
|
+
export type ChainNamespace = 'evm' | 'solana';
|
|
10
|
+
export interface ChainState {
|
|
11
|
+
address?: Address;
|
|
12
|
+
chainId?: ChainID;
|
|
13
|
+
}
|
|
14
|
+
export interface EvmChainState extends ChainState {
|
|
15
|
+
provider?: EIP1193Provider;
|
|
16
|
+
}
|
|
8
17
|
export type ValidInputTypes = Uint8Array | bigint | string | number | boolean;
|
|
9
18
|
export interface IFormoAnalytics {
|
|
10
19
|
page(category?: string, name?: string, properties?: IFormoEventProperties, context?: IFormoEventContext, callback?: (...args: unknown[]) => void): Promise<void>;
|
|
@@ -151,6 +160,14 @@ export interface Options {
|
|
|
151
160
|
* @requires @tanstack/react-query@>=5.0.0 (for mutation tracking)
|
|
152
161
|
*/
|
|
153
162
|
wagmi?: WagmiOptions;
|
|
163
|
+
/**
|
|
164
|
+
* Solana Wallet Adapter integration configuration
|
|
165
|
+
* When provided, the SDK will track Solana wallet events in addition to EVM wallet events
|
|
166
|
+
* This works alongside EIP-1193/Wagmi tracking - you can track both EVM and Solana wallets
|
|
167
|
+
* @requires @solana/wallet-adapter-base (optional peer dependency)
|
|
168
|
+
* @requires @solana/wallet-adapter-react (optional peer dependency, for React apps)
|
|
169
|
+
*/
|
|
170
|
+
solana?: SolanaOptions;
|
|
154
171
|
/**
|
|
155
172
|
* Custom API host for sending events through your own domain to bypass ad blockers
|
|
156
173
|
* - If not provided, events are sent directly to events.formo.so
|
|
@@ -44,9 +44,9 @@ export interface DetectAPIEvent {
|
|
|
44
44
|
}
|
|
45
45
|
export interface IdentifyAPIEvent {
|
|
46
46
|
type: "identify";
|
|
47
|
-
address:
|
|
48
|
-
providerName
|
|
49
|
-
rdns
|
|
47
|
+
address: Address;
|
|
48
|
+
providerName?: string;
|
|
49
|
+
rdns?: string;
|
|
50
50
|
userId?: Nullable<string>;
|
|
51
51
|
}
|
|
52
52
|
export interface ChainAPIEvent {
|
|
@@ -65,6 +65,7 @@ export interface TransactionAPIEvent {
|
|
|
65
65
|
transactionHash?: string;
|
|
66
66
|
function_name?: string;
|
|
67
67
|
function_args?: Record<string, unknown>;
|
|
68
|
+
builder_codes?: string;
|
|
68
69
|
}
|
|
69
70
|
export interface SignatureAPIEvent {
|
|
70
71
|
type: "signature";
|
|
@@ -26,4 +26,25 @@ export declare const getValidAddress: (address: Address | null | undefined) => s
|
|
|
26
26
|
*/
|
|
27
27
|
export declare const isBlockedAddress: (address: Address | null | undefined) => boolean;
|
|
28
28
|
export declare const toChecksumAddress: (address: Address) => string;
|
|
29
|
+
/**
|
|
30
|
+
* Validates an EVM address and returns it in checksummed format.
|
|
31
|
+
* @param address The address to validate
|
|
32
|
+
* @returns The checksummed address or undefined if invalid
|
|
33
|
+
*/
|
|
34
|
+
export declare const validateAndChecksumAddress: (address: string) => Address | undefined;
|
|
35
|
+
/**
|
|
36
|
+
* Validates an address for both EVM and Solana chains.
|
|
37
|
+
* For EVM addresses, returns checksummed format.
|
|
38
|
+
* For Solana addresses, returns the Base58 address as-is.
|
|
39
|
+
*
|
|
40
|
+
* When chainId is explicitly provided, validation is strict:
|
|
41
|
+
* - Solana chainId → only Solana validation
|
|
42
|
+
* - Non-Solana chainId → only EVM validation
|
|
43
|
+
* When chainId is omitted, EVM is tried first with Solana fallback.
|
|
44
|
+
*
|
|
45
|
+
* @param address The address to validate
|
|
46
|
+
* @param chainId Optional chain ID to determine address type
|
|
47
|
+
* @returns The validated address or undefined if invalid
|
|
48
|
+
*/
|
|
49
|
+
export declare const validateAddress: (address: string, chainId?: number) => Address | undefined;
|
|
29
50
|
//# sourceMappingURL=address.d.ts.map
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.toChecksumAddress = exports.isBlockedAddress = exports.getValidAddress = exports.isValidAddress = void 0;
|
|
3
|
+
exports.validateAddress = exports.validateAndChecksumAddress = exports.toChecksumAddress = exports.isBlockedAddress = exports.getValidAddress = exports.isValidAddress = void 0;
|
|
4
4
|
var keccak_js_1 = require("ethereum-cryptography/keccak.js");
|
|
5
5
|
var utils_js_1 = require("ethereum-cryptography/utils.js");
|
|
6
6
|
var validators_1 = require("../validators");
|
|
7
7
|
var object_1 = require("../validators/object");
|
|
8
8
|
var constants_1 = require("../constants");
|
|
9
|
+
var address_1 = require("../solana/address");
|
|
10
|
+
var types_1 = require("../solana/types");
|
|
9
11
|
/**
|
|
10
12
|
* Private helper function to validate and trim an address
|
|
11
13
|
* @param address The address to validate and trim
|
|
@@ -85,4 +87,49 @@ var toChecksumAddress = function (address) {
|
|
|
85
87
|
return checksumAddress;
|
|
86
88
|
};
|
|
87
89
|
exports.toChecksumAddress = toChecksumAddress;
|
|
90
|
+
/**
|
|
91
|
+
* Validates an EVM address and returns it in checksummed format.
|
|
92
|
+
* @param address The address to validate
|
|
93
|
+
* @returns The checksummed address or undefined if invalid
|
|
94
|
+
*/
|
|
95
|
+
var validateAndChecksumAddress = function (address) {
|
|
96
|
+
var validAddress = (0, exports.getValidAddress)(address);
|
|
97
|
+
return validAddress ? (0, exports.toChecksumAddress)(validAddress) : undefined;
|
|
98
|
+
};
|
|
99
|
+
exports.validateAndChecksumAddress = validateAndChecksumAddress;
|
|
100
|
+
/**
|
|
101
|
+
* Validates an address for both EVM and Solana chains.
|
|
102
|
+
* For EVM addresses, returns checksummed format.
|
|
103
|
+
* For Solana addresses, returns the Base58 address as-is.
|
|
104
|
+
*
|
|
105
|
+
* When chainId is explicitly provided, validation is strict:
|
|
106
|
+
* - Solana chainId → only Solana validation
|
|
107
|
+
* - Non-Solana chainId → only EVM validation
|
|
108
|
+
* When chainId is omitted, EVM is tried first with Solana fallback.
|
|
109
|
+
*
|
|
110
|
+
* @param address The address to validate
|
|
111
|
+
* @param chainId Optional chain ID to determine address type
|
|
112
|
+
* @returns The validated address or undefined if invalid
|
|
113
|
+
*/
|
|
114
|
+
var validateAddress = function (address, chainId) {
|
|
115
|
+
var solanaChainIds = Object.values(types_1.SOLANA_CHAIN_IDS);
|
|
116
|
+
// Explicit Solana chainId → validate ONLY as Solana
|
|
117
|
+
if (chainId !== undefined && chainId !== null && solanaChainIds.includes(chainId)) {
|
|
118
|
+
return (0, address_1.getValidSolanaAddress)(address) || undefined;
|
|
119
|
+
}
|
|
120
|
+
// Explicit non-Solana chainId → validate ONLY as EVM
|
|
121
|
+
if (chainId !== undefined && chainId !== null) {
|
|
122
|
+
return (0, exports.validateAndChecksumAddress)(address);
|
|
123
|
+
}
|
|
124
|
+
// No chainId → try EVM first, then Solana fallback
|
|
125
|
+
var validEvmAddress = (0, exports.validateAndChecksumAddress)(address);
|
|
126
|
+
if (validEvmAddress) {
|
|
127
|
+
return validEvmAddress;
|
|
128
|
+
}
|
|
129
|
+
if ((0, address_1.isSolanaAddress)(address)) {
|
|
130
|
+
return (0, address_1.getValidSolanaAddress)(address) || undefined;
|
|
131
|
+
}
|
|
132
|
+
return undefined;
|
|
133
|
+
};
|
|
134
|
+
exports.validateAddress = validateAddress;
|
|
88
135
|
//# sourceMappingURL=address.js.map
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ERC-8021 Builder Code Extraction
|
|
3
|
+
*
|
|
4
|
+
* Extracts builder codes from transaction calldata by parsing the ERC-8021
|
|
5
|
+
* data suffix. The suffix is appended to the end of calldata and parsed
|
|
6
|
+
* backwards:
|
|
7
|
+
*
|
|
8
|
+
* [original calldata] [schemaData] [schemaId (1 byte)] [ercMarker (16 bytes)]
|
|
9
|
+
*
|
|
10
|
+
* Schema 0 (canonical registry):
|
|
11
|
+
* [codes (variable ASCII)] [codesLength (1 byte)] [schemaId 0x00] [ercMarker]
|
|
12
|
+
*
|
|
13
|
+
* Schema 1 (custom registry):
|
|
14
|
+
* [registryAddress (20 bytes)] [chainId (variable)] [chainIdLength (1 byte)]
|
|
15
|
+
* [codes (variable ASCII)] [codesLength (1 byte)] [schemaId 0x01] [ercMarker]
|
|
16
|
+
*
|
|
17
|
+
* - ercMarker: 0x80218021802180218021802180218021 (16 bytes)
|
|
18
|
+
* - codes: ASCII-encoded entity codes delimited by 0x2C (comma)
|
|
19
|
+
*
|
|
20
|
+
* @see https://docs.base.org/base-chain/builder-codes/builder-codes
|
|
21
|
+
* @see https://www.erc8021.com/
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* Extract builder codes from transaction calldata by parsing the ERC-8021 suffix.
|
|
25
|
+
*
|
|
26
|
+
* @param data - The transaction calldata hex string (with or without 0x prefix)
|
|
27
|
+
* @returns A comma-separated string of builder codes (e.g. "uniswap,base"), or undefined if no valid ERC-8021 suffix is found
|
|
28
|
+
*/
|
|
29
|
+
export declare function extractBuilderCodes(data: string | undefined | null): string | undefined;
|
|
30
|
+
//# sourceMappingURL=builderCode.d.ts.map
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ERC-8021 Builder Code Extraction
|
|
4
|
+
*
|
|
5
|
+
* Extracts builder codes from transaction calldata by parsing the ERC-8021
|
|
6
|
+
* data suffix. The suffix is appended to the end of calldata and parsed
|
|
7
|
+
* backwards:
|
|
8
|
+
*
|
|
9
|
+
* [original calldata] [schemaData] [schemaId (1 byte)] [ercMarker (16 bytes)]
|
|
10
|
+
*
|
|
11
|
+
* Schema 0 (canonical registry):
|
|
12
|
+
* [codes (variable ASCII)] [codesLength (1 byte)] [schemaId 0x00] [ercMarker]
|
|
13
|
+
*
|
|
14
|
+
* Schema 1 (custom registry):
|
|
15
|
+
* [registryAddress (20 bytes)] [chainId (variable)] [chainIdLength (1 byte)]
|
|
16
|
+
* [codes (variable ASCII)] [codesLength (1 byte)] [schemaId 0x01] [ercMarker]
|
|
17
|
+
*
|
|
18
|
+
* - ercMarker: 0x80218021802180218021802180218021 (16 bytes)
|
|
19
|
+
* - codes: ASCII-encoded entity codes delimited by 0x2C (comma)
|
|
20
|
+
*
|
|
21
|
+
* @see https://docs.base.org/base-chain/builder-codes/builder-codes
|
|
22
|
+
* @see https://www.erc8021.com/
|
|
23
|
+
*/
|
|
24
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
+
exports.extractBuilderCodes = extractBuilderCodes;
|
|
26
|
+
/** The 16-byte ERC-8021 marker appended at the very end of calldata */
|
|
27
|
+
var ERC_MARKER = "80218021802180218021802180218021";
|
|
28
|
+
/** Length of the ERC marker in hex characters (16 bytes = 32 hex chars) */
|
|
29
|
+
var ERC_MARKER_HEX_LENGTH = 32;
|
|
30
|
+
/** Supported schema IDs */
|
|
31
|
+
var SCHEMA_ID_CANONICAL = "00";
|
|
32
|
+
var SCHEMA_ID_CUSTOM_REGISTRY = "01";
|
|
33
|
+
/** Comma delimiter (0x2C) used to separate multiple codes */
|
|
34
|
+
var COMMA_BYTE = 0x2c;
|
|
35
|
+
/**
|
|
36
|
+
* Decode the codes field from a hex string into a comma-separated string.
|
|
37
|
+
* Validates that all bytes are printable ASCII (0x20–0x7E).
|
|
38
|
+
*
|
|
39
|
+
* @param codesHex - Hex string of the codes field
|
|
40
|
+
* @returns Comma-separated builder codes string, or undefined if invalid
|
|
41
|
+
*/
|
|
42
|
+
function decodeCodes(codesHex) {
|
|
43
|
+
var bytes = [];
|
|
44
|
+
for (var i = 0; i < codesHex.length; i += 2) {
|
|
45
|
+
var byte = parseInt(codesHex.slice(i, i + 2), 16);
|
|
46
|
+
// Reject NaN (invalid hex), non-printable or non-ASCII bytes
|
|
47
|
+
if (isNaN(byte) || byte < 0x20 || byte > 0x7e) {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
bytes.push(byte);
|
|
51
|
+
}
|
|
52
|
+
// Split on comma delimiter and decode each code as ASCII
|
|
53
|
+
var codes = [];
|
|
54
|
+
var current = [];
|
|
55
|
+
for (var _i = 0, bytes_1 = bytes; _i < bytes_1.length; _i++) {
|
|
56
|
+
var byte = bytes_1[_i];
|
|
57
|
+
if (byte === COMMA_BYTE) {
|
|
58
|
+
if (current.length > 0) {
|
|
59
|
+
codes.push(String.fromCharCode.apply(String, current));
|
|
60
|
+
current = [];
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
current.push(byte);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
// Push the last code segment
|
|
68
|
+
if (current.length > 0) {
|
|
69
|
+
codes.push(String.fromCharCode.apply(String, current));
|
|
70
|
+
}
|
|
71
|
+
return codes.length > 0 ? codes.join(",") : undefined;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Read codesLength and codes from the hex string ending at the given position.
|
|
75
|
+
*
|
|
76
|
+
* @param hex - Full hex string (lowercase, no 0x prefix)
|
|
77
|
+
* @param endPos - Hex char position where codesLength byte ends (i.e. start of schemaId)
|
|
78
|
+
* @returns Object with decoded codes string and the hex char position where codes start, or undefined
|
|
79
|
+
*/
|
|
80
|
+
function readCodes(hex, endPos) {
|
|
81
|
+
// Read codesLength (1 byte before endPos)
|
|
82
|
+
var codesLengthStart = endPos - 2;
|
|
83
|
+
if (codesLengthStart < 0) {
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
var codesLength = parseInt(hex.slice(codesLengthStart, endPos), 16);
|
|
87
|
+
if (codesLength === 0 || isNaN(codesLength)) {
|
|
88
|
+
return undefined;
|
|
89
|
+
}
|
|
90
|
+
// Read the codes field
|
|
91
|
+
var codesHexLength = codesLength * 2;
|
|
92
|
+
var codesStart = codesLengthStart - codesHexLength;
|
|
93
|
+
if (codesStart < 0) {
|
|
94
|
+
return undefined;
|
|
95
|
+
}
|
|
96
|
+
var codesHex = hex.slice(codesStart, codesLengthStart);
|
|
97
|
+
var codes = decodeCodes(codesHex);
|
|
98
|
+
if (!codes) {
|
|
99
|
+
return undefined;
|
|
100
|
+
}
|
|
101
|
+
return { codes: codes, codesStart: codesStart };
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Extract builder codes from transaction calldata by parsing the ERC-8021 suffix.
|
|
105
|
+
*
|
|
106
|
+
* @param data - The transaction calldata hex string (with or without 0x prefix)
|
|
107
|
+
* @returns A comma-separated string of builder codes (e.g. "uniswap,base"), or undefined if no valid ERC-8021 suffix is found
|
|
108
|
+
*/
|
|
109
|
+
function extractBuilderCodes(data) {
|
|
110
|
+
if (!data || typeof data !== "string") {
|
|
111
|
+
return undefined;
|
|
112
|
+
}
|
|
113
|
+
// Normalize: remove 0x prefix and work with lowercase hex
|
|
114
|
+
var hex = data.startsWith("0x") || data.startsWith("0X")
|
|
115
|
+
? data.slice(2).toLowerCase()
|
|
116
|
+
: data.toLowerCase();
|
|
117
|
+
// Minimum suffix: 1+ byte codes + 1 byte codesLength + 1 byte schemaId + 16 bytes marker = 19 bytes = 38 hex chars
|
|
118
|
+
if (hex.length < 38) {
|
|
119
|
+
return undefined;
|
|
120
|
+
}
|
|
121
|
+
// Step 1: Check last 16 bytes for ERC marker
|
|
122
|
+
var markerStart = hex.length - ERC_MARKER_HEX_LENGTH;
|
|
123
|
+
var marker = hex.slice(markerStart);
|
|
124
|
+
if (marker !== ERC_MARKER) {
|
|
125
|
+
return undefined;
|
|
126
|
+
}
|
|
127
|
+
// Step 2: Read schemaId (1 byte before the marker)
|
|
128
|
+
var schemaIdStart = markerStart - 2;
|
|
129
|
+
if (schemaIdStart < 0) {
|
|
130
|
+
return undefined;
|
|
131
|
+
}
|
|
132
|
+
var schemaId = hex.slice(schemaIdStart, markerStart);
|
|
133
|
+
// Step 3: Parse based on schemaId
|
|
134
|
+
if (schemaId === SCHEMA_ID_CANONICAL || schemaId === SCHEMA_ID_CUSTOM_REGISTRY) {
|
|
135
|
+
// Both Schema 0 and Schema 1 have codes in the same position
|
|
136
|
+
// (immediately before schemaId when parsing backwards)
|
|
137
|
+
var result = readCodes(hex, schemaIdStart);
|
|
138
|
+
return result === null || result === void 0 ? void 0 : result.codes;
|
|
139
|
+
}
|
|
140
|
+
// Unknown schema - cannot parse
|
|
141
|
+
return undefined;
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=builderCode.js.map
|
|
@@ -16,6 +16,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./address"), exports);
|
|
18
18
|
__exportStar(require("./base"), exports);
|
|
19
|
+
__exportStar(require("./builderCode"), exports);
|
|
19
20
|
__exportStar(require("./converter"), exports);
|
|
20
21
|
__exportStar(require("./generate"), exports);
|
|
21
22
|
__exportStar(require("./hash"), exports);
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const version = "1.
|
|
1
|
+
export declare const version = "1.28.0";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/dist/cjs/src/version.js
CHANGED
|
@@ -3,5 +3,5 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.version = void 0;
|
|
4
4
|
// This file is auto-generated by scripts/update-version.js during npm version
|
|
5
5
|
// Do not edit manually - it will be overwritten
|
|
6
|
-
exports.version = '1.
|
|
6
|
+
exports.version = '1.28.0';
|
|
7
7
|
//# sourceMappingURL=version.js.map
|
|
@@ -58,6 +58,7 @@ exports.WagmiEventHandler = void 0;
|
|
|
58
58
|
var events_1 = require("../types/events");
|
|
59
59
|
var logger_1 = require("../logger");
|
|
60
60
|
var utils_1 = require("./utils");
|
|
61
|
+
var builderCode_1 = require("../utils/builderCode");
|
|
61
62
|
/**
|
|
62
63
|
* Built-in transaction fields that could collide with function args.
|
|
63
64
|
* Defined at module level to avoid recreating on every method call.
|
|
@@ -72,6 +73,7 @@ var RESERVED_FIELDS = new Set([
|
|
|
72
73
|
"transactionHash",
|
|
73
74
|
"function_name",
|
|
74
75
|
"function_args",
|
|
76
|
+
"builder_codes",
|
|
75
77
|
]);
|
|
76
78
|
/**
|
|
77
79
|
* Clean up old entries from a Set to prevent memory leaks.
|
|
@@ -386,7 +388,7 @@ var WagmiEventHandler = /** @class */ (function () {
|
|
|
386
388
|
chainId: chainId,
|
|
387
389
|
blockNumber: (_a = receipt === null || receipt === void 0 ? void 0 : receipt.blockNumber) === null || _a === void 0 ? void 0 : _a.toString(),
|
|
388
390
|
});
|
|
389
|
-
this.formo.transaction(__assign(__assign(__assign(__assign(__assign({ status: txStatus, chainId: chainId || 0, address: address, transactionHash: transactionHash }, ((pendingTx === null || pendingTx === void 0 ? void 0 : pendingTx.data) && { data: pendingTx.data })), ((pendingTx === null || pendingTx === void 0 ? void 0 : pendingTx.to) && { to: pendingTx.to })), ((pendingTx === null || pendingTx === void 0 ? void 0 : pendingTx.value) && { value: pendingTx.value })), ((pendingTx === null || pendingTx === void 0 ? void 0 : pendingTx.function_name) && { function_name: pendingTx.function_name })), ((pendingTx === null || pendingTx === void 0 ? void 0 : pendingTx.function_args) && { function_args: pendingTx.function_args })),
|
|
391
|
+
this.formo.transaction(__assign(__assign(__assign(__assign(__assign(__assign({ status: txStatus, chainId: chainId || 0, address: address, transactionHash: transactionHash }, ((pendingTx === null || pendingTx === void 0 ? void 0 : pendingTx.data) && { data: pendingTx.data })), ((pendingTx === null || pendingTx === void 0 ? void 0 : pendingTx.to) && { to: pendingTx.to })), ((pendingTx === null || pendingTx === void 0 ? void 0 : pendingTx.value) && { value: pendingTx.value })), ((pendingTx === null || pendingTx === void 0 ? void 0 : pendingTx.function_name) && { function_name: pendingTx.function_name })), ((pendingTx === null || pendingTx === void 0 ? void 0 : pendingTx.function_args) && { function_args: pendingTx.function_args })), ((pendingTx === null || pendingTx === void 0 ? void 0 : pendingTx.builder_codes) && { builder_codes: pendingTx.builder_codes })),
|
|
390
392
|
// Spread function args as additional properties (only colliding keys are prefixed)
|
|
391
393
|
pendingTx === null || pendingTx === void 0 ? void 0 : pendingTx.safeFunctionArgs);
|
|
392
394
|
// Clean up the pending transaction after confirmation
|
|
@@ -540,7 +542,7 @@ var WagmiEventHandler = /** @class */ (function () {
|
|
|
540
542
|
var value = (_a = variables.value) === null || _a === void 0 ? void 0 : _a.toString();
|
|
541
543
|
if (mutationType === "writeContract") {
|
|
542
544
|
// For writeContract, extract function info and encode data
|
|
543
|
-
var abi = variables.abi, fnName = variables.functionName, args = variables.args, contractAddress = variables.address;
|
|
545
|
+
var abi = variables.abi, fnName = variables.functionName, args = variables.args, contractAddress = variables.address, dataSuffix = variables.dataSuffix;
|
|
544
546
|
to = contractAddress;
|
|
545
547
|
function_name = fnName;
|
|
546
548
|
if (abi && fnName) {
|
|
@@ -549,7 +551,8 @@ var WagmiEventHandler = /** @class */ (function () {
|
|
|
549
551
|
// Encode the function data synchronously if viem is available
|
|
550
552
|
var encodedData = (0, utils_1.encodeWriteContractData)(abi, fnName, args);
|
|
551
553
|
if (encodedData) {
|
|
552
|
-
|
|
554
|
+
// Include dataSuffix (ERC-8021 builder code) so extractBuilderCodes sees full calldata
|
|
555
|
+
data = (0, utils_1.concatCalldataWithSuffix)(encodedData, dataSuffix);
|
|
553
556
|
logger_1.logger.debug("WagmiEventHandler: Encoded writeContract data", data.substring(0, 10));
|
|
554
557
|
}
|
|
555
558
|
}
|
|
@@ -560,14 +563,9 @@ var WagmiEventHandler = /** @class */ (function () {
|
|
|
560
563
|
data = variables.data;
|
|
561
564
|
to = variables.to;
|
|
562
565
|
}
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
address: userAddress,
|
|
567
|
-
chainId: chainId,
|
|
568
|
-
transactionHash: transactionHash,
|
|
569
|
-
function_name: function_name,
|
|
570
|
-
});
|
|
566
|
+
// Extract builder codes from transaction data (ERC-8021)
|
|
567
|
+
var builder_codes = (0, builderCode_1.extractBuilderCodes)(data);
|
|
568
|
+
logger_1.logger.info("WagmiEventHandler: Tracking transaction event", __assign({ status: status_2, mutationType: mutationType, address: userAddress, chainId: chainId, transactionHash: transactionHash, function_name: function_name }, (builder_codes && { builder_codes: builder_codes })));
|
|
571
569
|
// Build safeFunctionArgs with collision handling and struct flattening
|
|
572
570
|
var safeFunctionArgs = (0, utils_1.buildSafeFunctionArgs)(function_args, RESERVED_FIELDS);
|
|
573
571
|
// Store transaction details for BROADCASTED status to use in CONFIRMED/REVERTED
|
|
@@ -575,7 +573,7 @@ var WagmiEventHandler = /** @class */ (function () {
|
|
|
575
573
|
// Include the sender address to handle wallet switches between broadcast and confirmation
|
|
576
574
|
if (status_2 === events_1.TransactionStatus.BROADCASTED && transactionHash) {
|
|
577
575
|
var normalizedHash = transactionHash.toLowerCase();
|
|
578
|
-
var txDetails = __assign(__assign(__assign(__assign(__assign(__assign({ address: userAddress }, (data && { data: data })), (to && { to: to })), (value && { value: value })), (function_name && { function_name: function_name })), (function_args && { function_args: function_args })), (safeFunctionArgs && { safeFunctionArgs: safeFunctionArgs }));
|
|
576
|
+
var txDetails = __assign(__assign(__assign(__assign(__assign(__assign(__assign({ address: userAddress }, (data && { data: data })), (to && { to: to })), (value && { value: value })), (function_name && { function_name: function_name })), (function_args && { function_args: function_args })), (builder_codes && { builder_codes: builder_codes })), (safeFunctionArgs && { safeFunctionArgs: safeFunctionArgs }));
|
|
579
577
|
this.pendingTransactions.set(normalizedHash, txDetails);
|
|
580
578
|
logger_1.logger.debug("WagmiEventHandler: Stored pending transaction for confirmation", {
|
|
581
579
|
transactionHash: normalizedHash,
|
|
@@ -589,7 +587,7 @@ var WagmiEventHandler = /** @class */ (function () {
|
|
|
589
587
|
}
|
|
590
588
|
}
|
|
591
589
|
}
|
|
592
|
-
this.formo.transaction(__assign(__assign(__assign(__assign(__assign(__assign({ status: status_2, chainId: chainId || 0, address: userAddress }, (data && { data: data })), (to && { to: to })), (value && { value: value })), (transactionHash && { transactionHash: transactionHash })), (function_name && { function_name: function_name })), (function_args && { function_args: function_args })),
|
|
590
|
+
this.formo.transaction(__assign(__assign(__assign(__assign(__assign(__assign(__assign({ status: status_2, chainId: chainId || 0, address: userAddress }, (data && { data: data })), (to && { to: to })), (value && { value: value })), (transactionHash && { transactionHash: transactionHash })), (function_name && { function_name: function_name })), (function_args && { function_args: function_args })), (builder_codes && { builder_codes: builder_codes })),
|
|
593
591
|
// Spread function args as additional properties (only colliding keys are prefixed)
|
|
594
592
|
safeFunctionArgs);
|
|
595
593
|
}
|
|
@@ -647,7 +645,7 @@ var WagmiEventHandler = /** @class */ (function () {
|
|
|
647
645
|
* Clean up all subscriptions
|
|
648
646
|
*/
|
|
649
647
|
WagmiEventHandler.prototype.cleanup = function () {
|
|
650
|
-
logger_1.logger.
|
|
648
|
+
logger_1.logger.debug("WagmiEventHandler: Cleaning up subscriptions");
|
|
651
649
|
for (var _i = 0, _a = this.unsubscribers; _i < _a.length; _i++) {
|
|
652
650
|
var unsubscribe = _a[_i];
|
|
653
651
|
try {
|
|
@@ -661,7 +659,7 @@ var WagmiEventHandler = /** @class */ (function () {
|
|
|
661
659
|
this.processedMutations.clear();
|
|
662
660
|
this.processedQueries.clear();
|
|
663
661
|
this.pendingTransactions.clear();
|
|
664
|
-
logger_1.logger.
|
|
662
|
+
logger_1.logger.debug("WagmiEventHandler: Cleanup complete");
|
|
665
663
|
};
|
|
666
664
|
return WagmiEventHandler;
|
|
667
665
|
}());
|
|
@@ -40,6 +40,11 @@ export interface AbiOutput {
|
|
|
40
40
|
components?: AbiOutput[];
|
|
41
41
|
internalType?: string;
|
|
42
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* Concatenate encoded calldata with an optional ERC-8021 dataSuffix (e.g. builder codes).
|
|
45
|
+
* Uses viem's concatHex when available for correct hex handling.
|
|
46
|
+
*/
|
|
47
|
+
export declare function concatCalldataWithSuffix(encodedData: string, dataSuffix: string | undefined): string;
|
|
43
48
|
/**
|
|
44
49
|
* Encode writeContract data using viem's encodeFunctionData
|
|
45
50
|
*
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
exports.flattenObject = flattenObject;
|
|
10
|
+
exports.concatCalldataWithSuffix = concatCalldataWithSuffix;
|
|
10
11
|
exports.encodeWriteContractData = encodeWriteContractData;
|
|
11
12
|
exports.extractFunctionArgs = extractFunctionArgs;
|
|
12
13
|
exports.buildSafeFunctionArgs = buildSafeFunctionArgs;
|
|
@@ -82,6 +83,7 @@ function tryLoadViem() {
|
|
|
82
83
|
if (viem === null || viem === void 0 ? void 0 : viem.encodeFunctionData) {
|
|
83
84
|
viemModule = {
|
|
84
85
|
encodeFunctionData: viem.encodeFunctionData,
|
|
86
|
+
concatHex: viem.concatHex,
|
|
85
87
|
};
|
|
86
88
|
return viemModule;
|
|
87
89
|
}
|
|
@@ -92,6 +94,24 @@ function tryLoadViem() {
|
|
|
92
94
|
viemModule = null;
|
|
93
95
|
return null;
|
|
94
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* Concatenate encoded calldata with an optional ERC-8021 dataSuffix (e.g. builder codes).
|
|
99
|
+
* Uses viem's concatHex when available for correct hex handling.
|
|
100
|
+
*/
|
|
101
|
+
function concatCalldataWithSuffix(encodedData, dataSuffix) {
|
|
102
|
+
if (!dataSuffix || dataSuffix === "0x") {
|
|
103
|
+
return encodedData;
|
|
104
|
+
}
|
|
105
|
+
var viem = tryLoadViem();
|
|
106
|
+
if (viem === null || viem === void 0 ? void 0 : viem.concatHex) {
|
|
107
|
+
return viem.concatHex([
|
|
108
|
+
encodedData,
|
|
109
|
+
dataSuffix,
|
|
110
|
+
]);
|
|
111
|
+
}
|
|
112
|
+
var suffixHex = dataSuffix.replace(/^0x/i, "");
|
|
113
|
+
return "".concat(encodedData).concat(suffixHex);
|
|
114
|
+
}
|
|
95
115
|
/**
|
|
96
116
|
* Encode writeContract data using viem's encodeFunctionData
|
|
97
117
|
*
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import { EIP6963ProviderDetail } from "mipd";
|
|
2
2
|
import { Address, ChainID, Config, EIP1193Provider, IFormoAnalytics, IFormoEventContext, IFormoEventProperties, Options, SignatureStatus, TransactionStatus } from "./types";
|
|
3
|
+
import { SolanaManager } from "./solana/SolanaManager";
|
|
3
4
|
export declare class FormoAnalytics implements IFormoAnalytics {
|
|
4
5
|
readonly writeKey: string;
|
|
5
6
|
options: Options;
|
|
6
|
-
private
|
|
7
|
+
private _chainState;
|
|
8
|
+
private _activeNamespace?;
|
|
9
|
+
private get _provider();
|
|
10
|
+
private set _provider(value);
|
|
11
|
+
private get _evmAddress();
|
|
12
|
+
private get _evmChainId();
|
|
7
13
|
private _providerListenersMap;
|
|
8
14
|
private session;
|
|
9
15
|
private eventManager;
|
|
@@ -29,6 +35,11 @@ export declare class FormoAnalytics implements IFormoAnalytics {
|
|
|
29
35
|
* Only initialized when options.wagmi is provided
|
|
30
36
|
*/
|
|
31
37
|
private wagmiHandler?;
|
|
38
|
+
/**
|
|
39
|
+
* Solana integration manager for tracking Solana wallet events.
|
|
40
|
+
* Only initialized when options.solana is provided or via formo.solana.
|
|
41
|
+
*/
|
|
42
|
+
private solanaManager?;
|
|
32
43
|
/**
|
|
33
44
|
* Flag indicating if Wagmi mode is enabled
|
|
34
45
|
* When true, EIP-1193 provider wrapping is skipped
|
|
@@ -139,7 +150,7 @@ export declare class FormoAnalytics implements IFormoAnalytics {
|
|
|
139
150
|
* @param {(...args: unknown[]) => void} callback
|
|
140
151
|
* @returns {Promise<void>}
|
|
141
152
|
*/
|
|
142
|
-
transaction({ status, chainId, address, data, to, value, transactionHash, function_name, function_args, }: {
|
|
153
|
+
transaction({ status, chainId, address, data, to, value, transactionHash, function_name, function_args, builder_codes, }: {
|
|
143
154
|
status: TransactionStatus;
|
|
144
155
|
chainId: ChainID;
|
|
145
156
|
address: Address;
|
|
@@ -149,20 +160,38 @@ export declare class FormoAnalytics implements IFormoAnalytics {
|
|
|
149
160
|
transactionHash?: string;
|
|
150
161
|
function_name?: string;
|
|
151
162
|
function_args?: Record<string, unknown>;
|
|
163
|
+
builder_codes?: string;
|
|
152
164
|
}, properties?: IFormoEventProperties, context?: IFormoEventContext, callback?: (...args: unknown[]) => void): Promise<void>;
|
|
153
165
|
/**
|
|
154
166
|
* Emits an identify event with current wallet address and provider info.
|
|
155
|
-
*
|
|
156
|
-
* @param {string} params.
|
|
157
|
-
* @param {string} params.
|
|
158
|
-
* @param {string} params.
|
|
159
|
-
* @param {
|
|
167
|
+
*
|
|
168
|
+
* @param {string} params.address - Wallet address
|
|
169
|
+
* @param {string} params.userId - External user ID
|
|
170
|
+
* @param {string} params.rdns - Provider reverse domain name
|
|
171
|
+
* @param {string} params.providerName - Provider display name
|
|
172
|
+
* @param {IFormoEventProperties} properties - Additional properties to include with the identify event
|
|
160
173
|
* @param {IFormoEventContext} context
|
|
161
174
|
* @param {(...args: unknown[]) => void} callback
|
|
162
175
|
* @returns {Promise<void>}
|
|
176
|
+
*
|
|
177
|
+
* @example
|
|
178
|
+
* ```ts
|
|
179
|
+
* // Basic identify
|
|
180
|
+
* formo.identify({ address: '0x...', userId: 'user123' });
|
|
181
|
+
*
|
|
182
|
+
* // With Privy user
|
|
183
|
+
* import { parsePrivyProperties } from '@formo/analytics';
|
|
184
|
+
* const { user } = usePrivy();
|
|
185
|
+
* if (user) {
|
|
186
|
+
* const { properties, wallets } = parsePrivyProperties(user);
|
|
187
|
+
* for (const wallet of wallets) {
|
|
188
|
+
* formo.identify({ address: wallet.address, userId: user.id }, properties);
|
|
189
|
+
* }
|
|
190
|
+
* }
|
|
191
|
+
* ```
|
|
163
192
|
*/
|
|
164
193
|
identify(params?: {
|
|
165
|
-
address
|
|
194
|
+
address: Address;
|
|
166
195
|
providerName?: string;
|
|
167
196
|
userId?: string;
|
|
168
197
|
rdns?: string;
|
|
@@ -258,6 +287,19 @@ export declare class FormoAnalytics implements IFormoAnalytics {
|
|
|
258
287
|
get providers(): readonly EIP6963ProviderDetail[];
|
|
259
288
|
private detectWallets;
|
|
260
289
|
get provider(): EIP1193Provider | undefined;
|
|
290
|
+
/**
|
|
291
|
+
* Access the Solana integration manager.
|
|
292
|
+
* Lazily creates one if not already initialized.
|
|
293
|
+
*
|
|
294
|
+
* @example
|
|
295
|
+
* ```tsx
|
|
296
|
+
* formo.solana.setWallet(wallet);
|
|
297
|
+
* formo.solana.setConnection(connection);
|
|
298
|
+
* formo.solana.setCluster("devnet");
|
|
299
|
+
* formo.solana.syncWalletState();
|
|
300
|
+
* ```
|
|
301
|
+
*/
|
|
302
|
+
get solana(): SolanaManager;
|
|
261
303
|
private getAddress;
|
|
262
304
|
private getAccounts;
|
|
263
305
|
private getCurrentChainId;
|
|
@@ -298,11 +340,26 @@ export declare class FormoAnalytics implements IFormoAnalytics {
|
|
|
298
340
|
*/
|
|
299
341
|
private handleProviderMismatch;
|
|
300
342
|
/**
|
|
301
|
-
*
|
|
302
|
-
|
|
303
|
-
|
|
343
|
+
* Determine which namespace a chainId belongs to.
|
|
344
|
+
*/
|
|
345
|
+
private getNamespace;
|
|
346
|
+
/**
|
|
347
|
+
* Update per-chain state and sync the derived currentAddress/currentChainId.
|
|
348
|
+
* Accepts either a namespace string ('evm'/'solana') or a chainId number
|
|
349
|
+
* to resolve the namespace automatically. When a chainId number is passed,
|
|
350
|
+
* it is also stored as the namespace's chainId (unless explicitly overridden
|
|
351
|
+
* in the update object).
|
|
352
|
+
*/
|
|
353
|
+
private setChainState;
|
|
354
|
+
/**
|
|
355
|
+
* Clear per-chain state for a given namespace (or chainId) and sync derived state.
|
|
356
|
+
*/
|
|
357
|
+
private clearChainState;
|
|
358
|
+
/**
|
|
359
|
+
* Synchronize currentAddress/currentChainId from the active namespace.
|
|
360
|
+
* Last-connected-chain-wins: _activeNamespace takes precedence.
|
|
304
361
|
*/
|
|
305
|
-
private
|
|
362
|
+
private syncDerivedState;
|
|
306
363
|
/**
|
|
307
364
|
* Helper method to clear the active provider state
|
|
308
365
|
* Centralizes provider clearing logic for consistency
|