-
Notifications
You must be signed in to change notification settings - Fork 8
Fetch offchain data aptos #22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
RodrigoAD
wants to merge
6
commits into
main
Choose a base branch
from
fetch-offchain-data-aptos
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
226913f
refactor offchain data input type and attestations clients
RodrigoAD 25d3167
abstract fetch offchain data input. add events translation
RodrigoAD 7c7549a
fix token amounts type
RodrigoAD afcb58a
add tests for fetch offchain token data v2
RodrigoAD 3c0622f
fix format
RodrigoAD 6a0021d
revert token amount type changes
RodrigoAD File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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 |
---|---|---|
|
@@ -5,3 +5,4 @@ dist/ | |
.env* | ||
coverage | ||
coverage-summary.txt | ||
.vscode |
This file contains hidden or 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,8 @@ | ||
export type Attestation = { | ||
attestation: string | ||
messageHash: string | ||
} | ||
|
||
export interface AttestationClient { | ||
getAttestation(hash: string): Promise<Attestation> | ||
} |
This file contains hidden or 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,3 @@ | ||
export * from './usdc.ts' | ||
export * from './lbtc.ts' | ||
export { type AttestationClient } from './client.ts' |
This file contains hidden or 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,64 @@ | ||
import type { Attestation, AttestationClient } from './client.ts' | ||
|
||
const LOMBARD_API_URL = { | ||
mainnet: 'https://mainnet.prod.lombard.finance', | ||
testnet: 'https://gastald-testnet.prod.lombard.finance', | ||
} | ||
|
||
type LombardAttestation = | ||
| { status: 'NOTARIZATION_STATUS_SESSION_APPROVED'; message_hash: string; attestation: string } | ||
| { status: string; message_hash: string } | ||
type AttestationsResponse = { attestations: Array<LombardAttestation> } | ||
|
||
export class LBTCAttestationClient implements AttestationClient { | ||
private readonly url: string | ||
|
||
constructor(isTestnet: boolean) { | ||
this.url = isTestnet ? LOMBARD_API_URL.testnet : LOMBARD_API_URL.mainnet | ||
} | ||
|
||
async getAttestation(hash: string): Promise<Attestation> { | ||
try { | ||
const res = await fetch(`${this.url}/api/bridge/v1/deposits/getByHash`, { | ||
method: 'POST', | ||
body: JSON.stringify({ messageHash: [hash] }), | ||
}) | ||
const json = (await res.json()) as AttestationsResponse | ||
|
||
const attestation = this.validateReponse(json, hash) | ||
return { attestation, messageHash: hash } | ||
} catch (e) { | ||
throw new Error( | ||
`Error while fetching for USDC attestation with CIRCLE: ${(e as Error)?.message}`, | ||
) | ||
} | ||
} | ||
|
||
private validateReponse(response: AttestationsResponse, hash: string): string { | ||
// Ideally done with zod | ||
if (response == null || !('attestations' in response)) { | ||
throw new Error( | ||
'Error while fetching LBTC attestation. Response: ' + JSON.stringify(response, null, 2), | ||
) | ||
} | ||
const attestation = response.attestations.find((att) => att.message_hash === hash) | ||
if (attestation == null) { | ||
throw new Error( | ||
'Could not find requested LBTC attestation with hash:' + | ||
hash + | ||
' in response: ' + | ||
JSON.stringify(response, null, 2), | ||
) | ||
} | ||
if ( | ||
attestation.status === 'NOTARIZATION_STATUS_SESSION_APPROVED' && | ||
'attestation' in attestation | ||
) { | ||
return attestation.attestation | ||
} | ||
throw new Error( | ||
'LBTC attestation is not approved or invalid. Response: ' + | ||
JSON.stringify(attestation, null, 2), | ||
) | ||
} | ||
} |
This file contains hidden or 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,43 @@ | ||
import type { Attestation, AttestationClient } from './client.ts' | ||
|
||
// Docs: https://developers.circle.com/api-reference/stablecoins/common/get-attestation | ||
const CIRCLE_API_URL = { | ||
mainnet: 'https://iris-api.circle.com/v1', | ||
testnet: 'https://iris-api-sandbox.circle.com/v1', | ||
} | ||
|
||
type AttestationResponse = | ||
| { error: 'string' } | ||
| { status: 'pending_confirmations' } | ||
| { status: 'complete'; attestation: string } | ||
|
||
export class USDCAttestationClient implements AttestationClient { | ||
private readonly url: string | ||
|
||
constructor(isTestnet: boolean) { | ||
this.url = isTestnet ? CIRCLE_API_URL.testnet : CIRCLE_API_URL.mainnet | ||
} | ||
|
||
async getAttestation(hash: string): Promise<Attestation> { | ||
try { | ||
const res = await fetch(`${this.url}/attestations/${hash}`) | ||
const json = (await res.json()) as AttestationResponse | ||
const attestation = this.validateReponse(json) | ||
return { attestation, messageHash: hash } | ||
} catch (e) { | ||
throw new Error( | ||
`Error while fetching for USDC attestation with CIRCLE: ${(e as Error)?.message}`, | ||
) | ||
} | ||
} | ||
|
||
private validateReponse(json: AttestationResponse): string { | ||
// Ideally we do this with zod or similar | ||
if (!('status' in json) || json.status !== 'complete' || !json.attestation) { | ||
throw new Error( | ||
'Could not fetch USDC attestation. Response: ' + JSON.stringify(json, null, 2), | ||
) | ||
} | ||
return json.attestation | ||
} | ||
} |
This file contains hidden or 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,46 @@ | ||
import type { ChainEvent } from './types.ts' | ||
|
||
// Reference https://github.com/aptos-labs/aptos-ts-sdk/blob/main/src/types/generated/operations.ts#L432 | ||
// We should get this from the aptos-ts-sdk | ||
export type AptosEvent = { | ||
account_address: string | ||
creation_number: unknown | ||
data: unknown | ||
event_index: unknown | ||
sequence_number: unknown | ||
transaction_block_height: unknown | ||
transaction_version: unknown | ||
type: string // something like "0x1::coin::WithdrawEvent", | ||
indexed_type: string | ||
} | ||
|
||
export const toChainEventFromAptos = (event: AptosEvent): ChainEvent => { | ||
return { | ||
id: event.type, | ||
index: event.event_index as number, | ||
address: event.account_address, | ||
data: event.data as string, | ||
indexedArgs: [], | ||
} | ||
} | ||
|
||
// TODO: Build specific USDC and LBTC event identification fns | ||
export const isAptosUSDCEvent = (_event: ChainEvent): boolean => { | ||
return false | ||
} | ||
|
||
export const isAptosTransferEvent = (_event: ChainEvent): boolean => { | ||
return false | ||
} | ||
|
||
export const isAptosBurnedEvent = (_event: ChainEvent): boolean => { | ||
return false | ||
} | ||
|
||
export const isAptosLBTCEvent = (_event: ChainEvent): boolean => { | ||
return false | ||
} | ||
|
||
export const getEVMLBTCDepositHashes = (_event: ChainEvent): string => { | ||
return '' | ||
} |
This file contains hidden or 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,28 @@ | ||
import { | ||
getEVMLBTCDepositHashes, | ||
isEVMBurnedEvent, | ||
isEVMLBTCEvent, | ||
isEVMTransferEvent, | ||
isEVMUSDCEvent, | ||
} from './evm.ts' | ||
import type { ChainEvent } from './types.ts' | ||
|
||
export const isUSDCEvent = (event: ChainEvent): boolean => { | ||
return isEVMUSDCEvent(event) // || isAptosUSDCEvent(event) ... | ||
} | ||
|
||
export const isTransferEvent = (event: ChainEvent): boolean => { | ||
return isEVMTransferEvent(event) | ||
} | ||
|
||
export const isBurnedEvent = (event: ChainEvent): boolean => { | ||
return isEVMBurnedEvent(event) | ||
} | ||
|
||
export const isLBTCEvent = (event: ChainEvent): boolean => { | ||
return isEVMLBTCEvent(event) | ||
} | ||
|
||
export const getLBTCDepositHashes = (event: ChainEvent): string => { | ||
return getEVMLBTCDepositHashes(event) | ||
} |
This file contains hidden or 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,53 @@ | ||
import { type Log, EventFragment, Interface } from 'ethers' | ||
import TokenPoolABI from '../../abi/BurnMintTokenPool_1_5_1.ts' | ||
import { lazyCached } from '../utils.ts' | ||
import type { ChainEvent } from './types.ts' | ||
|
||
export const toChainEventFromEVM = ( | ||
event: Pick<Log, 'topics' | 'index' | 'address' | 'data'>, | ||
): ChainEvent => { | ||
return { | ||
id: event.topics[0], | ||
index: event.index, | ||
address: event.address, | ||
data: event.data, | ||
indexedArgs: event.topics.slice(1), | ||
} | ||
} | ||
|
||
const TokenPoolInterface = lazyCached( | ||
`Interface BurnMintTokenPool 1.5.1`, | ||
() => new Interface(TokenPoolABI), | ||
) | ||
const BURNED_EVENT = TokenPoolInterface.getEvent('Burned')! | ||
const USDC_EVENT = EventFragment.from('MessageSent(bytes message)') | ||
const TRANSFER_EVENT = EventFragment.from('Transfer(address from, address to, uint256 value)') | ||
const LBTC_EVENT = EventFragment.from( | ||
'DepositToBridge(address fromAddress, bytes32 toAddress, bytes32 payloadHash, bytes payload)', | ||
) | ||
|
||
export const isEVMUSDCEvent = (event: ChainEvent): boolean => { | ||
return event.id === USDC_EVENT.topicHash | ||
} | ||
|
||
export const isEVMTransferEvent = (event: ChainEvent): boolean => { | ||
return event.id === TRANSFER_EVENT.topicHash | ||
} | ||
|
||
export const isEVMBurnedEvent = (event: ChainEvent): boolean => { | ||
return event.id === BURNED_EVENT.topicHash | ||
} | ||
|
||
export const isEVMLBTCEvent = (event: ChainEvent): boolean => { | ||
return event.id === LBTC_EVENT.topicHash | ||
} | ||
|
||
export const getEVMLBTCDepositHashes = (event: ChainEvent): string => { | ||
if (!isEVMLBTCEvent(event)) { | ||
throw new Error('Event is not a LiquidBTC deposit event') | ||
} | ||
if (event.indexedArgs.length < 3) { | ||
throw new Error('Event does not have a deposit hash') | ||
} | ||
return event.indexedArgs[2] | ||
} |
This file contains hidden or 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,4 @@ | ||
export { type ChainEvent } from './types.ts' | ||
export { toChainEventFromAptos } from './aptos.ts' | ||
export { toChainEventFromEVM } from './evm.ts' | ||
export * from './events.ts' |
This file contains hidden or 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,8 @@ | ||
// Common type able to represent an event from different chains | ||
export type ChainEvent = { | ||
id: string // eventSignature or topics[0] in EVM chains | ||
index: number // position of the event in the transaction | ||
address: string // account emitting the event | ||
data: string // data of the event | ||
indexedArgs: Array<string> // indexed arguments of the event. topics[1:] in EVM chains | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Small abstraction over the atts. clients, in case more come in