-
-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #154 from mich3lang3lo/feat/zeko-integration
feat: zeko providers
- Loading branch information
Showing
40 changed files
with
1,290 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
export * as MinaExplorer from './mina-explorer' | ||
export * as MinaNode from './mina-node' | ||
export * as Obscura from './obscura-provider' | ||
export * from './unified-providers' |
48 changes: 48 additions & 0 deletions
48
packages/providers/src/mina-node/account-info/account-info-provider.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import { | ||
AccountInfo, | ||
AccountInfoArgs, | ||
AccountInfoProvider | ||
} from '@palladxyz/mina-core' | ||
|
||
import { createGraphQLRequest } from '../utils/fetch-utils' | ||
import { healthCheck } from '../utils/health-check-utils' | ||
import { getTokenAccountInfoQuery } from './queries' | ||
|
||
export const createAccountInfoProvider = (url: string): AccountInfoProvider => { | ||
const getAccountInfo = async ( | ||
args: AccountInfoArgs | ||
): Promise<Record<string, AccountInfo>> => { | ||
const variables = { publicKey: args.publicKey } | ||
const query = getTokenAccountInfoQuery(args.tokenMap || { MINA: '1' }) | ||
const fetchGraphQL = createGraphQLRequest(url) | ||
const result = await fetchGraphQL(query, variables) | ||
|
||
if (!result.ok) { | ||
throw new Error(result.message) | ||
} | ||
|
||
const accountsData = result.data | ||
const accountsInfo: Record<string, AccountInfo> = {} | ||
|
||
for (const [key, account] of Object.entries(accountsData)) { | ||
if (account === null) { | ||
accountsInfo[key] = { | ||
balance: { total: 0 }, | ||
nonce: 0, | ||
inferredNonce: 0, | ||
delegate: '', | ||
publicKey: args.publicKey | ||
} | ||
} else { | ||
accountsInfo[key] = account as AccountInfo | ||
} | ||
} | ||
|
||
return accountsInfo | ||
} | ||
|
||
return { | ||
healthCheck: () => healthCheck(url), | ||
getAccountInfo | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './account-info-provider' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
export const healthCheckQuery = ` | ||
{ | ||
syncStatus | ||
} | ||
` | ||
|
||
export const getAccountBalance = ` | ||
query accountBalance($publicKey: PublicKey!) { | ||
account(publicKey: $publicKey) { | ||
balance { | ||
total | ||
}, | ||
nonce | ||
inferredNonce | ||
delegate | ||
publicKey | ||
} | ||
} | ||
` | ||
import { TokenIdMap } from '@palladxyz/mina-core' | ||
|
||
export function getTokenAccountInfoQuery(tokenIds: TokenIdMap): string { | ||
// Start with the base part of the query | ||
let queryString = `query tokenQuery($publicKey: PublicKey!) {\n` | ||
|
||
// Dynamically add account queries based on tokenIds | ||
Object.entries(tokenIds).forEach(([alias, tokenId]) => { | ||
queryString += ` ${alias}: account(token: "${tokenId}", publicKey: $publicKey) {\n ...AccountFields\n }\n` | ||
}) | ||
|
||
// Add the fragment definition | ||
queryString += `}\n\nfragment AccountFields on Account {\n balance {\n total\n }\n tokenSymbol\n tokenId\n nonce\n inferredNonce\n publicKey\n delegate\n}` | ||
|
||
return queryString | ||
} |
113 changes: 113 additions & 0 deletions
113
packages/providers/src/mina-node/block-listener/BlockListenerProvider.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
import { AccountInfo, AccountInfoArgs } from '@palladxyz/mina-core' | ||
import { ExecutionResult } from 'graphql' | ||
import { gql, GraphQLClient } from 'graphql-request' | ||
import { SubscriptionClient } from 'subscriptions-transport-ws' | ||
|
||
import { | ||
AccountData, | ||
AccountInfoGraphQLProvider | ||
} from '../account-info/AccountInfoProvider' | ||
import { getAccountBalance } from '../account-info/queries' | ||
|
||
interface BlockData { | ||
newBlock?: { | ||
creator?: string | ||
stateHash?: string | ||
protocolState?: { | ||
consensusState?: { | ||
blockHeight?: number | ||
} | ||
previousStateHash?: string | ||
} | ||
} | ||
} | ||
|
||
export class BlockListenerProvider { | ||
private accountInfoProvider: AccountInfoGraphQLProvider | ||
private subscriptionClient: SubscriptionClient | ||
private gqlClient: GraphQLClient | ||
|
||
constructor(minaGql: string, wsEndpoint: string) { | ||
this.accountInfoProvider = new AccountInfoGraphQLProvider(minaGql) | ||
this.subscriptionClient = new SubscriptionClient(wsEndpoint, { | ||
reconnect: true | ||
}) | ||
this.gqlClient = new GraphQLClient(minaGql) | ||
} | ||
|
||
listenToNewBlocks(publicKey: string) { | ||
const subscription = gql` | ||
subscription { | ||
newBlock(publicKey: "${publicKey}") { | ||
creator | ||
stateHash | ||
protocolState { | ||
consensusState { | ||
blockHeight | ||
} | ||
previousStateHash | ||
} | ||
} | ||
} | ||
` | ||
|
||
return this.subscriptionClient | ||
.request({ | ||
query: subscription | ||
}) | ||
.subscribe({ | ||
next: async (result: ExecutionResult) => { | ||
// Type guard | ||
if ('data' in result && 'newBlock' in result.data) { | ||
const data: BlockData = result.data | ||
if (data.newBlock) { | ||
console.log('Received block data:', data) | ||
const accountInfo = await this.getAccountInfo({ publicKey }) | ||
console.log('Received updated account info:', accountInfo) | ||
} else { | ||
console.error('No new block data in result:', result) | ||
} | ||
} else { | ||
console.error('Unexpected result:', result) | ||
} | ||
} | ||
}) | ||
} | ||
|
||
private async getAccountInfo(args: AccountInfoArgs): Promise<AccountInfo> { | ||
console.log('Initiating getAccountInfo with args:', args) | ||
const query = gql` | ||
${getAccountBalance} | ||
` | ||
try { | ||
console.log('Sending request for account info...') | ||
const data = (await this.gqlClient.request(query, { | ||
publicKey: args.publicKey | ||
})) as AccountData | ||
console.log('Received response for account info:', data) | ||
|
||
if (!data || !data.account) { | ||
throw new Error('Invalid account data response') | ||
} | ||
return data.account | ||
} catch (error: unknown) { | ||
console.error('Error in getAccountInfo:', error) | ||
// this can fail if the account doesn't exist yet on the chain & if the node is not available | ||
// perform health check to see if the node is available | ||
const healthCheckResponse = await this.accountInfoProvider.healthCheck() | ||
if (!healthCheckResponse.ok) { | ||
throw new Error('Node is not available') | ||
} | ||
// if the node is available, then the account doesn't exist yet | ||
// return an empty account | ||
console.log('Error in getAccountInfo, account does not exist yet!') | ||
return { | ||
balance: { total: 0 }, | ||
nonce: 0, | ||
inferredNonce: 0, | ||
delegate: '', | ||
publicKey: args.publicKey | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './BlockListenerProvider' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
export const healthCheckQuery = ` | ||
{ | ||
__schema { | ||
types { | ||
name | ||
} | ||
} | ||
} | ||
` |
59 changes: 59 additions & 0 deletions
59
packages/providers/src/mina-node/chain-history/chain-history-provider.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import { | ||
ChainHistoryProvider, | ||
Mina, | ||
TransactionsByAddressesArgs, | ||
TransactionsByIdsArgs | ||
} from '@palladxyz/mina-core' | ||
|
||
import { createGraphQLRequest } from '../utils/fetch-utils' | ||
import { | ||
healthCheck, | ||
healthCheckQueryArchive | ||
} from '../utils/health-check-utils' | ||
import { transactionsByAddressesQuery } from './queries' | ||
|
||
export const createChainHistoryProvider = ( | ||
url: string | ||
): ChainHistoryProvider => { | ||
const transactionsByAddresses = async ( | ||
args: TransactionsByAddressesArgs | ||
): Promise<Mina.TransactionBody[]> => { | ||
const { startAt, limit } = args.pagination || { startAt: 0, limit: 10 } | ||
// TODO: remove array of addresses from TransactionsByAddressesArgs | ||
const variables = { address: args.addresses[0], limit, offset: startAt } | ||
const query = transactionsByAddressesQuery | ||
const fetchGraphQL = createGraphQLRequest(url) | ||
const result = await fetchGraphQL(query, variables) | ||
|
||
if (!result.ok) { | ||
throw new Error(result.message) | ||
} | ||
|
||
const transactions = result.data.transactions | ||
|
||
return transactions | ||
} | ||
|
||
const transactionsByHashes = async ( | ||
args: TransactionsByIdsArgs | ||
): Promise<Mina.TransactionBody[]> => { | ||
const variables = { ids: args.ids } | ||
const query = transactionsByAddressesQuery | ||
const fetchGraphQL = createGraphQLRequest(url) | ||
const result = await fetchGraphQL(query, variables) | ||
|
||
if (!result.ok) { | ||
throw new Error(result.message) | ||
} | ||
|
||
const transactions = result.data | ||
|
||
return transactions | ||
} | ||
|
||
return { | ||
healthCheck: () => healthCheck(url, healthCheckQueryArchive), | ||
transactionsByAddresses, | ||
transactionsByHashes | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './chain-history-provider' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
export const transactionsByAddressesQuery = ` | ||
query Transactions($address: String!, $limit: Int) { | ||
transactions( | ||
query: { canonical: true, OR: [{ to: $address }, { from: $address }] } | ||
limit: $limit | ||
sortBy: DATETIME_DESC | ||
) { | ||
amount | ||
to | ||
token | ||
kind | ||
isDelegation | ||
hash | ||
from | ||
fee | ||
failureReason | ||
dateTime | ||
blockHeight | ||
} | ||
} | ||
` | ||
|
||
export const transactionsByHashesQuery = ` | ||
query Transaction($hash: String!) { | ||
transaction(query: { hash: $hash }) { | ||
amount | ||
blockHeight | ||
dateTime | ||
failureReason | ||
fee | ||
from | ||
hash | ||
id | ||
isDelegation | ||
kind | ||
memo | ||
nonce | ||
to | ||
token | ||
} | ||
} | ||
` |
27 changes: 27 additions & 0 deletions
27
packages/providers/src/mina-node/daemon-status/daemon-status-provider.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { DaemonStatus, DaemonStatusProvider } from '@palladxyz/mina-core' | ||
|
||
import { createGraphQLRequest } from '../utils/fetch-utils' | ||
import { healthCheck } from '../utils/health-check-utils' | ||
import { getDaemonStatusQuery } from './queries' | ||
|
||
export const createDaemonStatusProvider = ( | ||
url: string | ||
): DaemonStatusProvider => { | ||
const getDaemonStatus = async (): Promise<DaemonStatus> => { | ||
const fetchGraphQL = createGraphQLRequest(url) | ||
const result = await fetchGraphQL(getDaemonStatusQuery) | ||
|
||
if (!result.ok) { | ||
throw new Error(result.message) | ||
} | ||
|
||
const daemonStatus = result.data | ||
|
||
return daemonStatus | ||
} | ||
|
||
return { | ||
healthCheck: () => healthCheck(url), | ||
getDaemonStatus | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './daemon-status-provider' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
export const getDaemonStatusQuery = ` | ||
query { | ||
daemonStatus { | ||
chainId | ||
} | ||
} | ||
` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export * from './account-info' | ||
export * from './chain-history' | ||
export * from './daemon-status' | ||
export * from './tx-submit' | ||
export * from './types' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './tx-submit-provider' |
Oops, something went wrong.