@fuul/mcp-server 1.10.0 → 1.12.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.
Files changed (47) hide show
  1. package/dist/currencies/currency-handlers.d.ts +6 -0
  2. package/dist/currencies/currency-handlers.d.ts.map +1 -0
  3. package/dist/currencies/currency-handlers.js +59 -0
  4. package/dist/currencies/currency-handlers.js.map +1 -0
  5. package/dist/currencies/fetch-price-references.d.ts +11 -0
  6. package/dist/currencies/fetch-price-references.d.ts.map +1 -0
  7. package/dist/currencies/fetch-price-references.js +40 -0
  8. package/dist/currencies/fetch-price-references.js.map +1 -0
  9. package/dist/currencies/resolve-token-holder-price-reference.d.ts +26 -0
  10. package/dist/currencies/resolve-token-holder-price-reference.d.ts.map +1 -0
  11. package/dist/currencies/resolve-token-holder-price-reference.js +113 -0
  12. package/dist/currencies/resolve-token-holder-price-reference.js.map +1 -0
  13. package/dist/incentives/incentive-write-handlers.d.ts +2 -2
  14. package/dist/incentives/incentive-write-handlers.d.ts.map +1 -1
  15. package/dist/incentives/incentive-write-handlers.js +18 -12
  16. package/dist/incentives/incentive-write-handlers.js.map +1 -1
  17. package/dist/index.js +54 -11
  18. package/dist/index.js.map +1 -1
  19. package/dist/metadata-scope/resolve-draft-ids.d.ts +21 -0
  20. package/dist/metadata-scope/resolve-draft-ids.d.ts.map +1 -0
  21. package/dist/metadata-scope/resolve-draft-ids.js +91 -0
  22. package/dist/metadata-scope/resolve-draft-ids.js.map +1 -0
  23. package/dist/tools/tool-descriptions.d.ts +3 -0
  24. package/dist/tools/tool-descriptions.d.ts.map +1 -1
  25. package/dist/tools/tool-descriptions.js +32 -5
  26. package/dist/tools/tool-descriptions.js.map +1 -1
  27. package/dist/tools/tool-schemas.d.ts +291 -232
  28. package/dist/tools/tool-schemas.d.ts.map +1 -1
  29. package/dist/tools/tool-schemas.js +27 -0
  30. package/dist/tools/tool-schemas.js.map +1 -1
  31. package/dist/triggers/price-reference-guide.d.ts +38 -0
  32. package/dist/triggers/price-reference-guide.d.ts.map +1 -0
  33. package/dist/triggers/price-reference-guide.js +55 -0
  34. package/dist/triggers/price-reference-guide.js.map +1 -0
  35. package/dist/triggers/trigger-create-payload-guide.d.ts +26 -1
  36. package/dist/triggers/trigger-create-payload-guide.d.ts.map +1 -1
  37. package/dist/triggers/trigger-create-payload-guide.js +40 -7
  38. package/dist/triggers/trigger-create-payload-guide.js.map +1 -1
  39. package/dist/triggers/trigger-write-handlers.d.ts +1 -1
  40. package/dist/triggers/trigger-write-handlers.d.ts.map +1 -1
  41. package/dist/triggers/trigger-write-handlers.js +30 -6
  42. package/dist/triggers/trigger-write-handlers.js.map +1 -1
  43. package/dist/triggers/validate-token-holder-price-reference.d.ts +8 -0
  44. package/dist/triggers/validate-token-holder-price-reference.d.ts.map +1 -0
  45. package/dist/triggers/validate-token-holder-price-reference.js +49 -0
  46. package/dist/triggers/validate-token-holder-price-reference.js.map +1 -0
  47. package/package.json +1 -1
@@ -0,0 +1,6 @@
1
+ import type { FuulApiClient } from '../http/fuul-api-client.js';
2
+ import type { ListPriceReferencesInput, ResolveTokenHolderPriceReferenceInput } from '../tools/tool-schemas.js';
3
+ export declare function runListPriceReferences(api: FuulApiClient, input: ListPriceReferencesInput): Promise<unknown>;
4
+ export declare function runResolveTokenHolderPriceReference(api: FuulApiClient, input: ResolveTokenHolderPriceReferenceInput): Promise<unknown>;
5
+ export declare function enrichPriceReferencesResponse(raw: unknown): unknown;
6
+ //# sourceMappingURL=currency-handlers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"currency-handlers.d.ts","sourceRoot":"","sources":["../../src/currencies/currency-handlers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,KAAK,EAAE,wBAAwB,EAAE,qCAAqC,EAAE,MAAM,0BAA0B,CAAC;AAOhH,wBAAsB,sBAAsB,CAAC,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,wBAAwB,GAAG,OAAO,CAAC,OAAO,CAAC,CAalH;AAED,wBAAsB,mCAAmC,CAAC,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,qCAAqC,GAAG,OAAO,CAAC,OAAO,CAAC,CAuB5I;AAeD,wBAAgB,6BAA6B,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAYnE"}
@@ -0,0 +1,59 @@
1
+ import { TOKEN_HOLDER_PRICE_REFERENCE_GUIDE } from '../triggers/price-reference-guide.js';
2
+ import { fetchPriceReferences } from './fetch-price-references.js';
3
+ import { chainIdentifierFromChainId, resolveTokenHolderPriceReference } from './resolve-token-holder-price-reference.js';
4
+ const CURRENCIES_PATH = '/api/v1/currencies';
5
+ export async function runListPriceReferences(api, input) {
6
+ const query = {
7
+ price_reference: true,
8
+ page: 1,
9
+ page_size: 100,
10
+ };
11
+ if (input.chain_identifier != null && input.chain_identifier !== '') {
12
+ query.chain_identifier = input.chain_identifier;
13
+ }
14
+ const data = await api.getJson(CURRENCIES_PATH, { query });
15
+ return enrichPriceReferencesResponse(data);
16
+ }
17
+ export async function runResolveTokenHolderPriceReference(api, input) {
18
+ const chainIdentifier = resolveChainIdentifier(input);
19
+ const priceReferences = await fetchPriceReferences(api, chainIdentifier);
20
+ const result = resolveTokenHolderPriceReference({
21
+ token_address: input.token_address,
22
+ chain_identifier: chainIdentifier,
23
+ token_kind: input.token_kind,
24
+ decimals: input.decimals,
25
+ }, priceReferences);
26
+ return {
27
+ ...result,
28
+ next_step: result.status === 'needs_user_input'
29
+ ? 'Ask the user the questions_for_user, then call resolve_token_holder_price_reference again with token_kind and decimals before create_trigger.'
30
+ : result.status === 'resolved' || result.status === 'listed_use_same_address'
31
+ ? `Set trigger.context.volume_currency_expression to ${result.volume_currency_expression}, then create_trigger (dry_run then confirmed).`
32
+ : 'Review matching_references_by_decimals or contact Fuul support.',
33
+ };
34
+ }
35
+ function resolveChainIdentifier(input) {
36
+ if (input.chain_identifier != null && input.chain_identifier !== '') {
37
+ return input.chain_identifier;
38
+ }
39
+ if (input.chain_id != null) {
40
+ const mapped = chainIdentifierFromChainId(input.chain_id);
41
+ if (mapped) {
42
+ return mapped;
43
+ }
44
+ }
45
+ throw new Error('Provide chain_identifier (e.g. "ethereum") or a supported chain_id (e.g. 1).');
46
+ }
47
+ export function enrichPriceReferencesResponse(raw) {
48
+ if (!raw || typeof raw !== 'object') {
49
+ return {
50
+ results: [],
51
+ token_holder_price_reference_guide: TOKEN_HOLDER_PRICE_REFERENCE_GUIDE,
52
+ };
53
+ }
54
+ return {
55
+ ...raw,
56
+ token_holder_price_reference_guide: TOKEN_HOLDER_PRICE_REFERENCE_GUIDE,
57
+ };
58
+ }
59
+ //# sourceMappingURL=currency-handlers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"currency-handlers.js","sourceRoot":"","sources":["../../src/currencies/currency-handlers.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kCAAkC,EAAE,MAAM,sCAAsC,CAAC;AAC1F,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,0BAA0B,EAAE,gCAAgC,EAAE,MAAM,2CAA2C,CAAC;AAEzH,MAAM,eAAe,GAAG,oBAAoB,CAAC;AAE7C,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,GAAkB,EAAE,KAA+B;IAC9F,MAAM,KAAK,GAA4B;QACrC,eAAe,EAAE,IAAI;QACrB,IAAI,EAAE,CAAC;QACP,SAAS,EAAE,GAAG;KACf,CAAC;IAEF,IAAI,KAAK,CAAC,gBAAgB,IAAI,IAAI,IAAI,KAAK,CAAC,gBAAgB,KAAK,EAAE,EAAE,CAAC;QACpE,KAAK,CAAC,gBAAgB,GAAG,KAAK,CAAC,gBAAgB,CAAC;IAClD,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,eAAe,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IAC3D,OAAO,6BAA6B,CAAC,IAAI,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mCAAmC,CAAC,GAAkB,EAAE,KAA4C;IACxH,MAAM,eAAe,GAAG,sBAAsB,CAAC,KAAK,CAAC,CAAC;IACtD,MAAM,eAAe,GAAG,MAAM,oBAAoB,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC;IAEzE,MAAM,MAAM,GAAG,gCAAgC,CAC7C;QACE,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,gBAAgB,EAAE,eAAe;QACjC,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,QAAQ,EAAE,KAAK,CAAC,QAAQ;KACzB,EACD,eAAe,CAChB,CAAC;IAEF,OAAO;QACL,GAAG,MAAM;QACT,SAAS,EACP,MAAM,CAAC,MAAM,KAAK,kBAAkB;YAClC,CAAC,CAAC,+IAA+I;YACjJ,CAAC,CAAC,MAAM,CAAC,MAAM,KAAK,UAAU,IAAI,MAAM,CAAC,MAAM,KAAK,yBAAyB;gBAC3E,CAAC,CAAC,qDAAqD,MAAM,CAAC,0BAA0B,iDAAiD;gBACzI,CAAC,CAAC,iEAAiE;KAC1E,CAAC;AACJ,CAAC;AAED,SAAS,sBAAsB,CAAC,KAA4C;IAC1E,IAAI,KAAK,CAAC,gBAAgB,IAAI,IAAI,IAAI,KAAK,CAAC,gBAAgB,KAAK,EAAE,EAAE,CAAC;QACpE,OAAO,KAAK,CAAC,gBAAgB,CAAC;IAChC,CAAC;IACD,IAAI,KAAK,CAAC,QAAQ,IAAI,IAAI,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,0BAA0B,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC1D,IAAI,MAAM,EAAE,CAAC;YACX,OAAO,MAAM,CAAC;QAChB,CAAC;IACH,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,8EAA8E,CAAC,CAAC;AAClG,CAAC;AAED,MAAM,UAAU,6BAA6B,CAAC,GAAY;IACxD,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QACpC,OAAO;YACL,OAAO,EAAE,EAAE;YACX,kCAAkC,EAAE,kCAAkC;SACvE,CAAC;IACJ,CAAC;IAED,OAAO;QACL,GAAI,GAA+B;QACnC,kCAAkC,EAAE,kCAAkC;KACvE,CAAC;AACJ,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { FuulApiClient } from '../http/fuul-api-client.js';
2
+ export type PriceReferenceRow = {
3
+ id: string;
4
+ name: string;
5
+ identifier: string;
6
+ chain_identifier: string;
7
+ decimals: number;
8
+ };
9
+ export declare function fetchPriceReferences(api: FuulApiClient, chainIdentifier: string): Promise<PriceReferenceRow[]>;
10
+ export declare function parsePriceReferenceResults(raw: unknown): PriceReferenceRow[];
11
+ //# sourceMappingURL=fetch-price-references.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-price-references.d.ts","sourceRoot":"","sources":["../../src/currencies/fetch-price-references.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAIhE,MAAM,MAAM,iBAAiB,GAAG;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAWpH;AAED,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,OAAO,GAAG,iBAAiB,EAAE,CA6B5E"}
@@ -0,0 +1,40 @@
1
+ const CURRENCIES_PATH = '/api/v1/currencies';
2
+ export async function fetchPriceReferences(api, chainIdentifier) {
3
+ const data = await api.getJson(CURRENCIES_PATH, {
4
+ query: {
5
+ price_reference: true,
6
+ chain_identifier: chainIdentifier,
7
+ page: 1,
8
+ page_size: 100,
9
+ },
10
+ });
11
+ return parsePriceReferenceResults(data);
12
+ }
13
+ export function parsePriceReferenceResults(raw) {
14
+ if (!raw || typeof raw !== 'object') {
15
+ return [];
16
+ }
17
+ const results = raw.results;
18
+ if (!Array.isArray(results)) {
19
+ return [];
20
+ }
21
+ const rows = [];
22
+ for (const row of results) {
23
+ if (!row || typeof row !== 'object') {
24
+ continue;
25
+ }
26
+ const r = row;
27
+ if (typeof r.identifier !== 'string' || typeof r.name !== 'string' || typeof r.decimals !== 'number') {
28
+ continue;
29
+ }
30
+ rows.push({
31
+ id: typeof r.id === 'string' ? r.id : '',
32
+ name: r.name,
33
+ identifier: r.identifier,
34
+ chain_identifier: typeof r.chain_identifier === 'string' ? r.chain_identifier : '',
35
+ decimals: r.decimals,
36
+ });
37
+ }
38
+ return rows;
39
+ }
40
+ //# sourceMappingURL=fetch-price-references.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-price-references.js","sourceRoot":"","sources":["../../src/currencies/fetch-price-references.ts"],"names":[],"mappings":"AAEA,MAAM,eAAe,GAAG,oBAAoB,CAAC;AAU7C,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,GAAkB,EAAE,eAAuB;IACpF,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,eAAe,EAAE;QAC9C,KAAK,EAAE;YACL,eAAe,EAAE,IAAI;YACrB,gBAAgB,EAAE,eAAe;YACjC,IAAI,EAAE,CAAC;YACP,SAAS,EAAE,GAAG;SACf;KACF,CAAC,CAAC;IAEH,OAAO,0BAA0B,CAAC,IAAI,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,GAAY;IACrD,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QACpC,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,OAAO,GAAI,GAA6B,CAAC,OAAO,CAAC;IACvD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,IAAI,GAAwB,EAAE,CAAC;IACrC,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QAC1B,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;YACpC,SAAS;QACX,CAAC;QACD,MAAM,CAAC,GAAG,GAA8B,CAAC;QACzC,IAAI,OAAO,CAAC,CAAC,UAAU,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YACrG,SAAS;QACX,CAAC;QACD,IAAI,CAAC,IAAI,CAAC;YACR,EAAE,EAAE,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE;YACxC,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,UAAU,EAAE,CAAC,CAAC,UAAU;YACxB,gBAAgB,EAAE,OAAO,CAAC,CAAC,gBAAgB,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE;YAClF,QAAQ,EAAE,CAAC,CAAC,QAAQ;SACrB,CAAC,CAAC;IACL,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,26 @@
1
+ import type { PriceReferenceRow } from './fetch-price-references.js';
2
+ export type TokenKind = 'stablecoin' | 'variable';
3
+ export type TokenDecimals = 6 | 18;
4
+ export type ResolveTokenHolderPriceReferenceInput = {
5
+ token_address: string;
6
+ chain_identifier: string;
7
+ token_kind?: TokenKind;
8
+ decimals?: TokenDecimals;
9
+ };
10
+ export type ResolveTokenHolderPriceReferenceResult = {
11
+ token_address: string;
12
+ chain_identifier: string;
13
+ token_is_listed_as_price_reference: boolean;
14
+ status: 'listed_use_same_address' | 'resolved' | 'needs_user_input' | 'no_matching_reference';
15
+ volume_currency_expression: string | null;
16
+ assigned_reference: Pick<PriceReferenceRow, 'identifier' | 'name' | 'decimals'> | null;
17
+ reason: string;
18
+ questions_for_user?: string[];
19
+ matching_references_by_decimals?: Array<Pick<PriceReferenceRow, 'identifier' | 'name' | 'decimals'>>;
20
+ };
21
+ export declare function resolveTokenHolderPriceReference(input: ResolveTokenHolderPriceReferenceInput, priceReferences: PriceReferenceRow[]): ResolveTokenHolderPriceReferenceResult;
22
+ export declare function pickPriceReference(rows: PriceReferenceRow[], tokenKind: TokenKind, decimals: TokenDecimals): PriceReferenceRow | null;
23
+ /** chain_id (EVM) → currencies API chain_identifier */
24
+ export declare const CHAIN_ID_TO_IDENTIFIER: Record<number, string>;
25
+ export declare function chainIdentifierFromChainId(chainId: number): string | null;
26
+ //# sourceMappingURL=resolve-token-holder-price-reference.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-token-holder-price-reference.d.ts","sourceRoot":"","sources":["../../src/currencies/resolve-token-holder-price-reference.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAErE,MAAM,MAAM,SAAS,GAAG,YAAY,GAAG,UAAU,CAAC;AAClD,MAAM,MAAM,aAAa,GAAG,CAAC,GAAG,EAAE,CAAC;AAEnC,MAAM,MAAM,qCAAqC,GAAG;IAClD,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,QAAQ,CAAC,EAAE,aAAa,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,sCAAsC,GAAG;IACnD,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,kCAAkC,EAAE,OAAO,CAAC;IAC5C,MAAM,EAAE,yBAAyB,GAAG,UAAU,GAAG,kBAAkB,GAAG,uBAAuB,CAAC;IAC9F,0BAA0B,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1C,kBAAkB,EAAE,IAAI,CAAC,iBAAiB,EAAE,YAAY,GAAG,MAAM,GAAG,UAAU,CAAC,GAAG,IAAI,CAAC;IACvF,MAAM,EAAE,MAAM,CAAC;IACf,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,+BAA+B,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,iBAAiB,EAAE,YAAY,GAAG,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC;CACtG,CAAC;AAMF,wBAAgB,gCAAgC,CAC9C,KAAK,EAAE,qCAAqC,EAC5C,eAAe,EAAE,iBAAiB,EAAE,GACnC,sCAAsC,CAiExC;AAWD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,iBAAiB,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,aAAa,GAAG,iBAAiB,GAAG,IAAI,CAuBrI;AAgBD,uDAAuD;AACvD,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAMzD,CAAC;AAEF,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAEzE"}
@@ -0,0 +1,113 @@
1
+ import { isTokenListedAsPriceReference, normalizeEvmAddress } from '../triggers/price-reference-guide.js';
2
+ const STABLECOIN_18_PREFERRED_NAMES = ['DAI'];
3
+ const STABLECOIN_6_PREFERRED_NAMES = ['USDC'];
4
+ const VARIABLE_18_PREFERRED_NAMES = ['WETH', 'ETH', 'WSTETH'];
5
+ export function resolveTokenHolderPriceReference(input, priceReferences) {
6
+ const tokenAddress = input.token_address.trim();
7
+ const chainIdentifier = input.chain_identifier.trim();
8
+ const base = {
9
+ token_address: tokenAddress,
10
+ chain_identifier: chainIdentifier,
11
+ token_is_listed_as_price_reference: isTokenListedAsPriceReference(tokenAddress, priceReferences),
12
+ };
13
+ if (base.token_is_listed_as_price_reference) {
14
+ return {
15
+ ...base,
16
+ status: 'listed_use_same_address',
17
+ volume_currency_expression: tokenAddress,
18
+ assigned_reference: findListedRow(tokenAddress, priceReferences),
19
+ reason: 'Token is already a price reference in Fuul. Set context.volume_currency_expression to the same address as token_address, then create_trigger.',
20
+ };
21
+ }
22
+ if (input.token_kind == null || input.decimals == null) {
23
+ return {
24
+ ...base,
25
+ status: 'needs_user_input',
26
+ volume_currency_expression: null,
27
+ assigned_reference: null,
28
+ reason: 'Token is not a listed price reference. Ask the user before create_trigger, then call this tool again with token_kind and decimals.',
29
+ questions_for_user: [
30
+ 'Is this a stablecoin or a variable-price token? (stablecoin | variable)',
31
+ 'How many decimals does the token have? (6 or 18 — verify on Etherscan/Arbiscan/etc.)',
32
+ ],
33
+ matching_references_by_decimals: undefined,
34
+ };
35
+ }
36
+ const assigned = pickPriceReference(priceReferences, input.token_kind, input.decimals);
37
+ if (!assigned) {
38
+ const withDecimals = priceReferences.filter((r) => r.decimals === input.decimals);
39
+ return {
40
+ ...base,
41
+ status: 'no_matching_reference',
42
+ volume_currency_expression: null,
43
+ assigned_reference: null,
44
+ reason: `No price reference with ${input.decimals} decimals on ${chainIdentifier}. Contact Fuul support or pick manually from list_price_references.`,
45
+ matching_references_by_decimals: withDecimals.map((r) => ({
46
+ identifier: r.identifier,
47
+ name: r.name,
48
+ decimals: r.decimals,
49
+ })),
50
+ };
51
+ }
52
+ return {
53
+ ...base,
54
+ status: 'resolved',
55
+ volume_currency_expression: assigned.identifier,
56
+ assigned_reference: {
57
+ identifier: assigned.identifier,
58
+ name: assigned.name,
59
+ decimals: assigned.decimals,
60
+ },
61
+ reason: buildResolvedReason(input.token_kind, input.decimals, assigned),
62
+ };
63
+ }
64
+ function findListedRow(tokenAddress, rows) {
65
+ const normalized = normalizeEvmAddress(tokenAddress);
66
+ const row = rows.find((r) => normalizeEvmAddress(r.identifier) === normalized);
67
+ if (!row) {
68
+ return null;
69
+ }
70
+ return { identifier: row.identifier, name: row.name, decimals: row.decimals };
71
+ }
72
+ export function pickPriceReference(rows, tokenKind, decimals) {
73
+ const matchingDecimals = rows.filter((r) => r.decimals === decimals);
74
+ if (matchingDecimals.length === 0) {
75
+ return null;
76
+ }
77
+ const preferredNames = tokenKind === 'stablecoin'
78
+ ? decimals === 18
79
+ ? STABLECOIN_18_PREFERRED_NAMES
80
+ : STABLECOIN_6_PREFERRED_NAMES
81
+ : decimals === 18
82
+ ? VARIABLE_18_PREFERRED_NAMES
83
+ : STABLECOIN_6_PREFERRED_NAMES;
84
+ for (const name of preferredNames) {
85
+ const hit = matchingDecimals.find((r) => nameMatches(r.name, name));
86
+ if (hit) {
87
+ return hit;
88
+ }
89
+ }
90
+ return matchingDecimals[0] ?? null;
91
+ }
92
+ function nameMatches(currencyName, preferred) {
93
+ const n = currencyName.trim().toUpperCase();
94
+ const p = preferred.toUpperCase();
95
+ return n === p || n.startsWith(`${p} `) || n.startsWith(p);
96
+ }
97
+ function buildResolvedReason(tokenKind, decimals, assigned) {
98
+ return (`Assigned ${assigned.name} (${assigned.identifier}) as volume_currency_expression: ` +
99
+ `${tokenKind} with ${decimals} decimals → use a listed reference with matching decimals ` +
100
+ `(e.g. 18-decimal stablecoin on Ethereum → DAI). Put this address in context.volume_currency_expression, not the held token address.`);
101
+ }
102
+ /** chain_id (EVM) → currencies API chain_identifier */
103
+ export const CHAIN_ID_TO_IDENTIFIER = {
104
+ 1: 'ethereum',
105
+ 10: 'optimistic-ethereum',
106
+ 137: 'polygon',
107
+ 42161: 'arbitrum',
108
+ 8453: 'base',
109
+ };
110
+ export function chainIdentifierFromChainId(chainId) {
111
+ return CHAIN_ID_TO_IDENTIFIER[chainId] ?? null;
112
+ }
113
+ //# sourceMappingURL=resolve-token-holder-price-reference.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-token-holder-price-reference.js","sourceRoot":"","sources":["../../src/currencies/resolve-token-holder-price-reference.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import type { FuulApiClient } from '../http/fuul-api-client.js';
2
2
  import type { CreateIncentiveInput, DeleteIncentiveInput } from '../tools/tool-schemas.js';
3
- export declare function runCreateIncentive(api: FuulApiClient, input: CreateIncentiveInput): Promise<unknown>;
4
- export declare function runDeleteIncentive(api: FuulApiClient, input: DeleteIncentiveInput): Promise<unknown>;
3
+ export declare function runCreateIncentive(api: FuulApiClient, input: CreateIncentiveInput, toolTimeoutMs: number): Promise<unknown>;
4
+ export declare function runDeleteIncentive(api: FuulApiClient, input: DeleteIncentiveInput, toolTimeoutMs: number): Promise<unknown>;
5
5
  //# sourceMappingURL=incentive-write-handlers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"incentive-write-handlers.d.ts","sourceRoot":"","sources":["../../src/incentives/incentive-write-handlers.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAEhE,OAAO,KAAK,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAU3F,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,OAAO,CAAC,CAc1G;AAED,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,OAAO,CAAC,CAY1G"}
1
+ {"version":3,"file":"incentive-write-handlers.d.ts","sourceRoot":"","sources":["../../src/incentives/incentive-write-handlers.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAOhE,OAAO,KAAK,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAU3F,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,aAAa,EAClB,KAAK,EAAE,oBAAoB,EAC3B,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,OAAO,CAAC,CAyBlB;AAED,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,aAAa,EAClB,KAAK,EAAE,oBAAoB,EAC3B,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,OAAO,CAAC,CAsBlB"}
@@ -1,34 +1,40 @@
1
1
  import { assertWriteConfirmedOrDryRun } from '../agent/write-confirmation.js';
2
+ import { attachDraftIdResolution, resolveDraftConversionIdForWrite, resolveDraftTriggerIdsForWrite, } from '../metadata-scope/resolve-draft-ids.js';
2
3
  import { normalizePayoutTermBodyForPatch } from '../payouts/normalize-payout-term-body.js';
3
- function buildCreateIncentiveBody(input) {
4
+ function buildCreateIncentiveBody(input, triggerIds) {
4
5
  return {
5
6
  name: input.name,
6
- trigger_ids: input.trigger_ids,
7
+ trigger_ids: triggerIds,
7
8
  payout_terms: input.payout_terms.map((term) => normalizePayoutTermBodyForPatch(term)),
8
9
  };
9
10
  }
10
- export async function runCreateIncentive(api, input) {
11
+ export async function runCreateIncentive(api, input, toolTimeoutMs) {
11
12
  assertWriteConfirmedOrDryRun(input);
13
+ const triggerResolutions = await resolveDraftTriggerIdsForWrite(api, input.project_id, input.trigger_ids, toolTimeoutMs);
14
+ const resolvedTriggerIds = triggerResolutions.map((row) => row.resolved_draft_trigger_id);
12
15
  const path = `/api/v1/projects/${input.project_id}/incentives`;
13
- const body = buildCreateIncentiveBody(input);
16
+ const body = buildCreateIncentiveBody(input, resolvedTriggerIds);
14
17
  if (input.dry_run === true) {
15
- return {
18
+ return attachDraftIdResolution({
16
19
  dry_run: true,
17
20
  would_post: path,
18
21
  body,
19
- };
22
+ }, { triggers: triggerResolutions });
20
23
  }
21
- return api.postJson(path, body);
24
+ const result = await api.postJson(path, body);
25
+ return attachDraftIdResolution(result, { triggers: triggerResolutions });
22
26
  }
23
- export async function runDeleteIncentive(api, input) {
27
+ export async function runDeleteIncentive(api, input, toolTimeoutMs) {
24
28
  assertWriteConfirmedOrDryRun(input);
25
- const path = `/api/v1/projects/${input.project_id}/incentives/${input.conversion_id}`;
29
+ const resolution = await resolveDraftConversionIdForWrite(api, input.project_id, input.conversion_id, toolTimeoutMs);
30
+ const path = `/api/v1/projects/${input.project_id}/incentives/${resolution.resolved_draft_conversion_id}`;
26
31
  if (input.dry_run === true) {
27
- return {
32
+ return attachDraftIdResolution({
28
33
  dry_run: true,
29
34
  would_delete: path,
30
- };
35
+ }, resolution);
31
36
  }
32
- return api.deleteJson(path);
37
+ const result = await api.deleteJson(path);
38
+ return attachDraftIdResolution(result ?? { ok: true }, resolution);
33
39
  }
34
40
  //# sourceMappingURL=incentive-write-handlers.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"incentive-write-handlers.js","sourceRoot":"","sources":["../../src/incentives/incentive-write-handlers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAE9E,OAAO,EAAE,+BAA+B,EAAE,MAAM,0CAA0C,CAAC;AAG3F,SAAS,wBAAwB,CAAC,KAA2B;IAC3D,OAAO;QACL,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,YAAY,EAAE,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,+BAA+B,CAAC,IAA+B,CAAC,CAAC;KACjH,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,GAAkB,EAAE,KAA2B;IACtF,4BAA4B,CAAC,KAAK,CAAC,CAAC;IACpC,MAAM,IAAI,GAAG,oBAAoB,KAAK,CAAC,UAAU,aAAa,CAAC;IAC/D,MAAM,IAAI,GAAG,wBAAwB,CAAC,KAAK,CAAC,CAAC;IAE7C,IAAI,KAAK,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;QAC3B,OAAO;YACL,OAAO,EAAE,IAAI;YACb,UAAU,EAAE,IAAI;YAChB,IAAI;SACL,CAAC;IACJ,CAAC;IAED,OAAO,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AAClC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,GAAkB,EAAE,KAA2B;IACtF,4BAA4B,CAAC,KAAK,CAAC,CAAC;IACpC,MAAM,IAAI,GAAG,oBAAoB,KAAK,CAAC,UAAU,eAAe,KAAK,CAAC,aAAa,EAAE,CAAC;IAEtF,IAAI,KAAK,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;QAC3B,OAAO;YACL,OAAO,EAAE,IAAI;YACb,YAAY,EAAE,IAAI;SACnB,CAAC;IACJ,CAAC;IAED,OAAO,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;AAC9B,CAAC"}
1
+ {"version":3,"file":"incentive-write-handlers.js","sourceRoot":"","sources":["../../src/incentives/incentive-write-handlers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAE9E,OAAO,EACL,uBAAuB,EACvB,gCAAgC,EAChC,8BAA8B,GAC/B,MAAM,wCAAwC,CAAC;AAChD,OAAO,EAAE,+BAA+B,EAAE,MAAM,0CAA0C,CAAC;AAG3F,SAAS,wBAAwB,CAAC,KAA2B,EAAE,UAAoB;IACjF,OAAO;QACL,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,WAAW,EAAE,UAAU;QACvB,YAAY,EAAE,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,+BAA+B,CAAC,IAA+B,CAAC,CAAC;KACjH,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,GAAkB,EAClB,KAA2B,EAC3B,aAAqB;IAErB,4BAA4B,CAAC,KAAK,CAAC,CAAC;IACpC,MAAM,kBAAkB,GAAG,MAAM,8BAA8B,CAC7D,GAAG,EACH,KAAK,CAAC,UAAU,EAChB,KAAK,CAAC,WAAW,EACjB,aAAa,CACd,CAAC;IACF,MAAM,kBAAkB,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;IAC1F,MAAM,IAAI,GAAG,oBAAoB,KAAK,CAAC,UAAU,aAAa,CAAC;IAC/D,MAAM,IAAI,GAAG,wBAAwB,CAAC,KAAK,EAAE,kBAAkB,CAAC,CAAC;IAEjE,IAAI,KAAK,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;QAC3B,OAAO,uBAAuB,CAC5B;YACE,OAAO,EAAE,IAAI;YACb,UAAU,EAAE,IAAI;YAChB,IAAI;SACL,EACD,EAAE,QAAQ,EAAE,kBAAkB,EAAE,CACjC,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC9C,OAAO,uBAAuB,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,kBAAkB,EAAE,CAAC,CAAC;AAC3E,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,GAAkB,EAClB,KAA2B,EAC3B,aAAqB;IAErB,4BAA4B,CAAC,KAAK,CAAC,CAAC;IACpC,MAAM,UAAU,GAAG,MAAM,gCAAgC,CACvD,GAAG,EACH,KAAK,CAAC,UAAU,EAChB,KAAK,CAAC,aAAa,EACnB,aAAa,CACd,CAAC;IACF,MAAM,IAAI,GAAG,oBAAoB,KAAK,CAAC,UAAU,eAAe,UAAU,CAAC,4BAA4B,EAAE,CAAC;IAE1G,IAAI,KAAK,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;QAC3B,OAAO,uBAAuB,CAC5B;YACE,OAAO,EAAE,IAAI;YACb,YAAY,EAAE,IAAI;SACnB,EACD,UAAU,CACX,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IAC1C,OAAO,uBAAuB,CAAC,MAAM,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,UAAU,CAAC,CAAC;AACrE,CAAC"}
package/dist/index.js CHANGED
@@ -7,6 +7,7 @@ import { assertWriteConfirmedOrDryRun, WriteNotConfirmedError } from './agent/wr
7
7
  import { OAuthClient } from './auth/oauth-client.js';
8
8
  import { TokenStore } from './auth/token-store.js';
9
9
  import { loadEnv } from './config/env.js';
10
+ import { runListPriceReferences, runResolveTokenHolderPriceReference } from './currencies/currency-handlers.js';
10
11
  import { runCheckEventStatus, runSendBatchEvents, runSendEvent } from './events/events-handlers.js';
11
12
  import { ApiRequestError, FuulApiClient, NotLoggedInError } from './http/fuul-api-client.js';
12
13
  import { MissingProjectApiKeyError, resolveProjectApiKeyBearer } from './http/project-api-key-bearer.js';
@@ -14,11 +15,12 @@ import { enrichPayoutSchemasResponse } from './incentives/incentive-create-paylo
14
15
  import { runCreateIncentive, runDeleteIncentive } from './incentives/incentive-write-handlers.js';
15
16
  import { MetadataService } from './metadata/metadata-service.js';
16
17
  import { loadIncentivesListWithMetadataScope, loadIncentiveWithMetadataScope, loadProjectWithMetadataScope, } from './metadata-scope/fetch-project-config.js';
18
+ import { attachDraftIdResolution, resolveDraftConversionIdForWrite, resolveDraftTriggerIdForWrite } from './metadata-scope/resolve-draft-ids.js';
17
19
  import { normalizePayoutTermBodyForPatch } from './payouts/normalize-payout-term-body.js';
18
20
  import { runPayoutBatchAction } from './payouts/payout-batch-handlers.js';
19
21
  import { runDeleteUserReferrer, runGetUserReferrer, runRemoveUserFromReferralCode, runSwapUserReferralCode, runUpdateUserReferrer, runUseReferralCode, } from './referral-attribution/referral-attribution-handlers.js';
20
- import { APPROVE_PAYOUTS_DESCRIPTION, CHECK_EVENT_STATUS_DESCRIPTION, CREATE_INCENTIVE_DESCRIPTION, CREATE_PROJECT_AFFILIATE_PUBLIC_DESCRIPTION, CREATE_TRIGGER_DESCRIPTION, DELETE_INCENTIVE_DESCRIPTION, DELETE_TRIGGER_DESCRIPTION, DELETE_USER_REFERRER_DESCRIPTION, GET_AFFILIATE_PORTAL_STATS_DESCRIPTION, GET_INCENTIVE_DESCRIPTION, GET_PROJECT_AFFILIATE_PUBLIC_DESCRIPTION, GET_PROJECT_AFFILIATE_TOTAL_STATS_DESCRIPTION, GET_PROJECT_AFFILIATES_BREAKDOWN_DESCRIPTION, GET_PROJECT_DESCRIPTION, GET_TRIGGER_DESCRIPTION, GET_USER_REFERRER_DESCRIPTION, LIST_CHAINS_DESCRIPTION, LIST_INCENTIVES_DESCRIPTION, LIST_PAYOUT_SCHEMAS_DESCRIPTION, LIST_PAYOUTS_PENDING_APPROVAL_DESCRIPTION, LIST_PROJECTS_DESCRIPTION, LIST_REWARDS_PAYOUTS_DESCRIPTION, LIST_TRIGGER_TYPES_DESCRIPTION, PING_DESCRIPTION, REJECT_PAYOUTS_DESCRIPTION, REMOVE_USER_FROM_REFERRAL_CODE_DESCRIPTION, SEND_BATCH_EVENTS_DESCRIPTION, SEND_EVENT_DESCRIPTION, SWAP_USER_REFERRAL_CODE_DESCRIPTION, UPDATE_AUDIENCE_DESCRIPTION, UPDATE_PAYOUT_TERM_DESCRIPTION, UPDATE_PROJECT_AFFILIATE_PUBLIC_DESCRIPTION, UPDATE_PROJECT_TIER_DESCRIPTION, UPDATE_TRIGGER_DESCRIPTION, UPDATE_USER_REFERRER_DESCRIPTION, USE_REFERRAL_CODE_DESCRIPTION, WHOAMI_DESCRIPTION, } from './tools/tool-descriptions.js';
21
- import { checkEventStatusFieldsSchema, checkEventStatusInputSchema, createIncentiveFieldsSchema, createIncentiveInputSchema, createProjectAffiliatePublicFieldsSchema, createProjectAffiliatePublicInputSchema, createTriggerFieldsSchema, createTriggerInputSchema, deleteIncentiveFieldsSchema, deleteIncentiveInputSchema, deleteTriggerFieldsSchema, deleteTriggerInputSchema, deleteUserReferrerFieldsSchema, deleteUserReferrerInputSchema, getAffiliatePortalStatsSchema, getIncentiveInputSchema, getProjectAffiliatePublicInputSchema, getProjectAffiliatesBreakdownSchema, getProjectAffiliateTotalStatsSchema, getTriggerInputSchema, getUserReferrerFieldsSchema, getUserReferrerInputSchema, listPayoutsPendingApprovalSchema, listProjectsInputSchema, listRewardsPayoutsSchema, payoutBatchActionInputSchema, projectIdParamSchema, removeUserFromReferralCodeFieldsSchema, removeUserFromReferralCodeInputSchema, sendBatchEventsFieldsSchema, sendBatchEventsInputSchema, sendEventFieldsSchema, sendEventInputSchema, swapUserReferralCodeFieldsSchema, swapUserReferralCodeInputSchema, updateAudienceFieldsSchema, updateAudienceInputSchema, updatePayoutTermInputSchema, updateProjectAffiliatePublicFieldsSchema, updateProjectAffiliatePublicInputSchema, updateProjectTierFieldsSchema, updateProjectTierInputSchema, updateTriggerFieldsSchema, updateTriggerInputSchema, updateUserReferrerFieldsSchema, updateUserReferrerInputSchema, useReferralCodeFieldsSchema, useReferralCodeInputSchema, } from './tools/tool-schemas.js';
22
+ import { APPROVE_PAYOUTS_DESCRIPTION, CHECK_EVENT_STATUS_DESCRIPTION, CREATE_INCENTIVE_DESCRIPTION, CREATE_PROJECT_AFFILIATE_PUBLIC_DESCRIPTION, CREATE_TRIGGER_DESCRIPTION, DELETE_INCENTIVE_DESCRIPTION, DELETE_TRIGGER_DESCRIPTION, DELETE_USER_REFERRER_DESCRIPTION, GET_AFFILIATE_PORTAL_STATS_DESCRIPTION, GET_INCENTIVE_DESCRIPTION, GET_PROJECT_AFFILIATE_PUBLIC_DESCRIPTION, GET_PROJECT_AFFILIATE_TOTAL_STATS_DESCRIPTION, GET_PROJECT_AFFILIATES_BREAKDOWN_DESCRIPTION, GET_PROJECT_DESCRIPTION, GET_TRIGGER_DESCRIPTION, GET_USER_REFERRER_DESCRIPTION, LIST_CHAINS_DESCRIPTION, LIST_INCENTIVES_DESCRIPTION, LIST_PAYOUT_SCHEMAS_DESCRIPTION, LIST_PAYOUTS_PENDING_APPROVAL_DESCRIPTION, LIST_PRICE_REFERENCES_DESCRIPTION, LIST_PROJECTS_DESCRIPTION, LIST_REWARDS_PAYOUTS_DESCRIPTION, LIST_TRIGGER_TYPES_DESCRIPTION, PING_DESCRIPTION, REJECT_PAYOUTS_DESCRIPTION, REMOVE_USER_FROM_REFERRAL_CODE_DESCRIPTION, RESOLVE_TOKEN_HOLDER_PRICE_REFERENCE_DESCRIPTION, SEND_BATCH_EVENTS_DESCRIPTION, SEND_EVENT_DESCRIPTION, SWAP_USER_REFERRAL_CODE_DESCRIPTION, UPDATE_AUDIENCE_DESCRIPTION, UPDATE_PAYOUT_TERM_DESCRIPTION, UPDATE_PROJECT_AFFILIATE_PUBLIC_DESCRIPTION, UPDATE_PROJECT_TIER_DESCRIPTION, UPDATE_TRIGGER_DESCRIPTION, UPDATE_USER_REFERRER_DESCRIPTION, USE_REFERRAL_CODE_DESCRIPTION, WHOAMI_DESCRIPTION, } from './tools/tool-descriptions.js';
23
+ import { checkEventStatusFieldsSchema, checkEventStatusInputSchema, createIncentiveFieldsSchema, createIncentiveInputSchema, createProjectAffiliatePublicFieldsSchema, createProjectAffiliatePublicInputSchema, createTriggerFieldsSchema, createTriggerInputSchema, deleteIncentiveFieldsSchema, deleteIncentiveInputSchema, deleteTriggerFieldsSchema, deleteTriggerInputSchema, deleteUserReferrerFieldsSchema, deleteUserReferrerInputSchema, getAffiliatePortalStatsSchema, getIncentiveInputSchema, getProjectAffiliatePublicInputSchema, getProjectAffiliatesBreakdownSchema, getProjectAffiliateTotalStatsSchema, getTriggerInputSchema, getUserReferrerFieldsSchema, getUserReferrerInputSchema, listPayoutsPendingApprovalSchema, listPriceReferencesInputSchema, listProjectsInputSchema, listRewardsPayoutsSchema, payoutBatchActionInputSchema, projectIdParamSchema, removeUserFromReferralCodeFieldsSchema, removeUserFromReferralCodeInputSchema, resolveTokenHolderPriceReferenceFieldsSchema, resolveTokenHolderPriceReferenceInputSchema, sendBatchEventsFieldsSchema, sendBatchEventsInputSchema, sendEventFieldsSchema, sendEventInputSchema, swapUserReferralCodeFieldsSchema, swapUserReferralCodeInputSchema, updateAudienceFieldsSchema, updateAudienceInputSchema, updatePayoutTermInputSchema, updateProjectAffiliatePublicFieldsSchema, updateProjectAffiliatePublicInputSchema, updateProjectTierFieldsSchema, updateProjectTierInputSchema, updateTriggerFieldsSchema, updateTriggerInputSchema, updateUserReferrerFieldsSchema, updateUserReferrerInputSchema, useReferralCodeFieldsSchema, useReferralCodeInputSchema, } from './tools/tool-schemas.js';
22
24
  import { enrichTriggerTypesResponse } from './triggers/trigger-create-payload-guide.js';
23
25
  import { runCreateTrigger, runDeleteTrigger } from './triggers/trigger-write-handlers.js';
24
26
  import { compactQuery } from './util/compact-query.js';
@@ -84,6 +86,26 @@ async function main() {
84
86
  return toolErrorPayload(e);
85
87
  }
86
88
  });
89
+ server.tool('list_price_references', LIST_PRICE_REFERENCES_DESCRIPTION, listPriceReferencesInputSchema.shape, async (args) => {
90
+ try {
91
+ const parsed = listPriceReferencesInputSchema.parse(args);
92
+ const data = await withTimeout(runListPriceReferences(api, parsed), toolTimeoutMs, 'list_price_references');
93
+ return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
94
+ }
95
+ catch (e) {
96
+ return toolErrorPayload(e, 'Failed to list price references');
97
+ }
98
+ });
99
+ server.tool('resolve_token_holder_price_reference', RESOLVE_TOKEN_HOLDER_PRICE_REFERENCE_DESCRIPTION, resolveTokenHolderPriceReferenceFieldsSchema.shape, async (args) => {
100
+ try {
101
+ const parsed = resolveTokenHolderPriceReferenceInputSchema.parse(args);
102
+ const data = await withTimeout(runResolveTokenHolderPriceReference(api, parsed), toolTimeoutMs, 'resolve_token_holder_price_reference');
103
+ return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
104
+ }
105
+ catch (e) {
106
+ return toolErrorPayload(e, 'Failed to resolve token holder price reference');
107
+ }
108
+ });
87
109
  server.tool('list_trigger_types', LIST_TRIGGER_TYPES_DESCRIPTION, {}, async () => {
88
110
  try {
89
111
  const data = await withTimeout(metadata.getTriggerTypes(), toolTimeoutMs, 'list_trigger_types');
@@ -174,7 +196,7 @@ async function main() {
174
196
  server.tool('delete_trigger', DELETE_TRIGGER_DESCRIPTION, deleteTriggerFieldsSchema.shape, async (args) => {
175
197
  try {
176
198
  const parsed = deleteTriggerInputSchema.parse(args);
177
- const data = await withTimeout(runDeleteTrigger(api, parsed), toolTimeoutMs, 'delete_trigger');
199
+ const data = await withTimeout(runDeleteTrigger(api, parsed, toolTimeoutMs), toolTimeoutMs, 'delete_trigger');
178
200
  return { content: [{ type: 'text', text: stringifyToolPayload(data ?? { ok: true }, parsed.dry_run) }] };
179
201
  }
180
202
  catch (e) {
@@ -184,7 +206,7 @@ async function main() {
184
206
  server.tool('create_incentive', CREATE_INCENTIVE_DESCRIPTION, createIncentiveFieldsSchema.shape, async (args) => {
185
207
  try {
186
208
  const parsed = createIncentiveInputSchema.parse(args);
187
- const data = await withTimeout(runCreateIncentive(api, parsed), toolTimeoutMs, 'create_incentive');
209
+ const data = await withTimeout(runCreateIncentive(api, parsed, toolTimeoutMs), toolTimeoutMs, 'create_incentive');
188
210
  return { content: [{ type: 'text', text: stringifyToolPayload(data, parsed.dry_run) }] };
189
211
  }
190
212
  catch (e) {
@@ -194,7 +216,7 @@ async function main() {
194
216
  server.tool('delete_incentive', DELETE_INCENTIVE_DESCRIPTION, deleteIncentiveFieldsSchema.shape, async (args) => {
195
217
  try {
196
218
  const parsed = deleteIncentiveInputSchema.parse(args);
197
- const data = await withTimeout(runDeleteIncentive(api, parsed), toolTimeoutMs, 'delete_incentive');
219
+ const data = await withTimeout(runDeleteIncentive(api, parsed, toolTimeoutMs), toolTimeoutMs, 'delete_incentive');
198
220
  return { content: [{ type: 'text', text: stringifyToolPayload(data ?? { ok: true }, parsed.dry_run) }] };
199
221
  }
200
222
  catch (e) {
@@ -435,20 +457,28 @@ async function main() {
435
457
  try {
436
458
  const parsed = updatePayoutTermInputSchema.parse(args);
437
459
  assertWriteConfirmedOrDryRun(parsed);
438
- const path = `/api/v1/projects/${parsed.project_id}/conversions/${parsed.conversion_id}/payout_terms/${parsed.payout_term_id}`;
460
+ const conversionResolution = await resolveDraftConversionIdForWrite(api, parsed.project_id, parsed.conversion_id, toolTimeoutMs);
461
+ const path = `/api/v1/projects/${parsed.project_id}/conversions/${conversionResolution.resolved_draft_conversion_id}/payout_terms/${parsed.payout_term_id}`;
439
462
  const patchBody = normalizePayoutTermBodyForPatch(parsed.payout_term);
440
463
  if (parsed.dry_run === true) {
441
464
  return {
442
465
  content: [
443
466
  {
444
467
  type: 'text',
445
- text: JSON.stringify({ dry_run: true, would_patch: path, body: patchBody }, null, 2),
468
+ text: JSON.stringify(attachDraftIdResolution({ dry_run: true, would_patch: path, body: patchBody }, conversionResolution), null, 2),
446
469
  },
447
470
  ],
448
471
  };
449
472
  }
450
473
  const data = await withTimeout(api.patchJson(path, patchBody), toolTimeoutMs, 'update_payout_term');
451
- return { content: [{ type: 'text', text: stringifyToolPayload(data, parsed.dry_run) }] };
474
+ return {
475
+ content: [
476
+ {
477
+ type: 'text',
478
+ text: stringifyToolPayload(attachDraftIdResolution(data, conversionResolution), parsed.dry_run),
479
+ },
480
+ ],
481
+ };
452
482
  }
453
483
  catch (e) {
454
484
  return toolErrorPayload(e, 'Failed to update payout term');
@@ -485,7 +515,8 @@ async function main() {
485
515
  try {
486
516
  const parsed = updateTriggerInputSchema.parse(args);
487
517
  assertWriteConfirmedOrDryRun(parsed);
488
- const path = `/api/v1/projects/${parsed.project_id}/triggers/${parsed.trigger_id}`;
518
+ const triggerResolution = await resolveDraftTriggerIdForWrite(api, parsed.project_id, parsed.trigger_id, toolTimeoutMs);
519
+ const path = `/api/v1/projects/${parsed.project_id}/triggers/${triggerResolution.resolved_draft_trigger_id}`;
489
520
  const body = {};
490
521
  if (parsed.name !== undefined) {
491
522
  body.name = parsed.name;
@@ -534,11 +565,23 @@ async function main() {
534
565
  }
535
566
  if (parsed.dry_run === true) {
536
567
  return {
537
- content: [{ type: 'text', text: JSON.stringify({ dry_run: true, would_patch: path, body }, null, 2) }],
568
+ content: [
569
+ {
570
+ type: 'text',
571
+ text: JSON.stringify(attachDraftIdResolution({ dry_run: true, would_patch: path, body }, triggerResolution), null, 2),
572
+ },
573
+ ],
538
574
  };
539
575
  }
540
576
  const data = await withTimeout(api.patchJson(path, body), toolTimeoutMs, 'update_trigger');
541
- return { content: [{ type: 'text', text: stringifyToolPayload(data, parsed.dry_run) }] };
577
+ return {
578
+ content: [
579
+ {
580
+ type: 'text',
581
+ text: stringifyToolPayload(attachDraftIdResolution(data, triggerResolution), parsed.dry_run),
582
+ },
583
+ ],
584
+ };
542
585
  }
543
586
  catch (e) {
544
587
  return toolErrorPayload(e, 'Failed to update trigger');