Skip to content

Commit beb6940

Browse files
committed
Submit-query primitive
1 parent 2f8f9aa commit beb6940

File tree

1 file changed

+114
-0
lines changed

1 file changed

+114
-0
lines changed

src/primitives/submit-query.ts

+114
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import { getErrorMsg } from '../utils';
2+
import {
3+
BitteToolBuilder,
4+
BitteToolResult,
5+
GqlFetchResult,
6+
NearNetworkId,
7+
} from '../types';
8+
9+
export const GRAPH_ENDPOINTS = {
10+
mainnet: 'https://graph.mintbase.xyz/',
11+
testnet: 'https://graph.mintbase.xyz/testnet',
12+
};
13+
14+
type SubmitQueryParams = {
15+
query: string;
16+
network: NearNetworkId;
17+
};
18+
19+
export const submitQueryPrimitive: BitteToolBuilder<
20+
void,
21+
SubmitQueryParams,
22+
GqlFetchResult<unknown>
23+
> = () => ({
24+
toolSpec: {
25+
function: {
26+
name: 'submit-query',
27+
description: `Generate and submit GraphQL queries based on schema.
28+
- Limit results to 5 unless specified (max 20)
29+
- Fetch aggregations with '<field-name>_aggregate'
30+
- Always fetch 'metadata_id' for NFTs
31+
- Use model/view names as main query fields
32+
- Include relevant fields in selection set
33+
34+
Example:
35+
query FetchRecentListings {
36+
mb_views_active_listings(order_by: {created_at: desc}, limit: 5) {
37+
media title price created_at nft_contract_id token_id metadata_id
38+
}
39+
}
40+
`,
41+
parameters: {
42+
type: 'object',
43+
required: ['query', 'network'],
44+
properties: {
45+
query: {
46+
type: 'string',
47+
description: `GraphQL query based on this schema:
48+
SharedNFTFields: nft_contract_id, token_id, receipt_id, timestamp, reference, reference_hash, media, media_hash, title, description, extra, content_flag
49+
SharedContractFields: name, symbol, icon, spec, base_uri, owner_id, is_mintbase
50+
51+
Models:
52+
mb_store_minters: {...SharedNFTFields, minter_id}
53+
nft_approvals: {...SharedNFTFields, approved_account_id, approval_id}
54+
nft_attributes: {nft_metadata_id, ...SharedNFTFields, attribute_type, attribute_value, attribute_display_type}
55+
nft_contracts: {id, ...SharedContractFields, reference, reference_hash, created_at, created_receipt_id, content_flag, category}
56+
nft_metadata: {id, ...SharedNFTFields, reference_blob, minter}
57+
58+
Views:
59+
mb_views_nft_metadata: {id, ...SharedNFTFields, ...SharedContractFields, reference_blob, metadata_content_flag, nft_contract_reference, nft_contract_created_at, nft_contract_content_flag}
60+
mb_views_active_listings: {...SharedNFTFields, market_id, approval_id, created_at, kind, price, currency, listed_by, metadata_id, minter, reference_blob}
61+
mb_views_nft_tokens: {...SharedNFTFields, ...SharedContractFields, owner, mint_memo, last_transfer_timestamp, last_transfer_receipt_id, minted_timestamp, minted_receipt_id, burned_timestamp, burned_receipt_id, minter, copies, issued_at, expires_at, starts_at, updated_at, metadata_id, reference_blob, metadata_content_flag, nft_contract_reference, nft_contract_created_at, nft_contract_content_flag, royalties_percent, royalties, splits}
62+
mb_views_nft_tokens_with_listing: {...SharedNFTFields, owner, metadata_id, price, currency, reference_blob}
63+
mb_views_active_listings_by_contract: {...SharedNFTFields, market_id, approval_id, price, currency, created_at, metadata_id, listed_by, total_listings}`,
64+
},
65+
network: {
66+
type: 'string',
67+
enum: ['testnet', 'mainnet'],
68+
default: 'mainnet',
69+
description: 'Network to query.',
70+
},
71+
},
72+
},
73+
},
74+
type: 'function',
75+
},
76+
execute: async ({
77+
query,
78+
network,
79+
}: SubmitQueryParams): Promise<BitteToolResult<GqlFetchResult<unknown>>> => {
80+
const mintbaseGraphUrl = GRAPH_ENDPOINTS[network];
81+
82+
try {
83+
const request = await fetch(mintbaseGraphUrl, {
84+
method: 'POST',
85+
headers: {
86+
'Content-Type': 'application/json',
87+
'mb-api-key': 'omni-site',
88+
},
89+
body: JSON.stringify({
90+
query,
91+
network,
92+
}),
93+
});
94+
95+
const queryResponse: GqlFetchResult<unknown> = await request.json();
96+
97+
const queryData = queryResponse.data;
98+
99+
if (queryData) {
100+
return {
101+
data: queryData,
102+
};
103+
}
104+
105+
return {
106+
error: queryResponse.error || 'Query returned no data or error',
107+
};
108+
} catch (error) {
109+
return {
110+
error: getErrorMsg(error),
111+
};
112+
}
113+
},
114+
});

0 commit comments

Comments
 (0)