-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
25 changed files
with
603 additions
and
1,418 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 |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import NamadaConsole from './NamadaConsole' | ||
import NamadaChain from './NamadaChain' | ||
import NamadaConnection from './NamadaConnection' | ||
import NamadaTransaction from './NamadaTransaction' | ||
import { Decode, initDecoder } from './NamadaDecode' | ||
import * as Identity from './NamadaIdentity' | ||
export { | ||
Decode, | ||
initDecoder, | ||
NamadaConsole as Console, | ||
NamadaChain as Chain, | ||
NamadaConnection as Connection, | ||
NamadaTransaction as Transaction, | ||
Identity | ||
} | ||
export const testnetChainId = NamadaChain.testnetChainId | ||
export const testnetURLs = NamadaChain.testnetURLs | ||
export function connect (...args: Parameters<typeof NamadaChain.connect>) { | ||
return NamadaChain.connect(...args) | ||
} | ||
export function testnet (...args: Parameters<typeof NamadaChain.testnet>) { | ||
return NamadaChain.testnet(...args) | ||
} | ||
export function mainnet (...args: never) { | ||
throw new Error( | ||
'Connection details for Namada mainnet are not built into Fadroma yet. ' + | ||
'You can pass them to Namada.connect function if you have them.' | ||
) | ||
} |
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,133 @@ | ||
import { Block } from '@fadroma/cw' | ||
import type { Chain as Namada } from './Namada' | ||
import { Decode } from './NamadaDecode' | ||
import Transaction, { NamadaUndecodedTransaction } from './NamadaTransaction' | ||
|
||
export default class NamadaBlock extends Block { | ||
|
||
constructor ({ | ||
header, responses, ...properties | ||
}: ConstructorParameters<typeof Block>[0] | ||
& Pick<NamadaBlock, 'header'|'responses'|'chain'> | ||
) { | ||
super(properties) | ||
this.#chain = properties.chain | ||
this.#responses = responses | ||
this.header = header | ||
} | ||
|
||
#chain: Namada | ||
get chain (): Namada { | ||
return this.#chain | ||
} | ||
|
||
#responses?: { | ||
block: { url: string, response: string } | ||
results: { url: string, response: string } | ||
} | ||
get responses () { | ||
return this.#responses | ||
} | ||
|
||
/** Block header. */ | ||
header: { | ||
version: object | ||
chainId: string | ||
height: bigint | ||
time: string | ||
lastBlockId: string | ||
lastCommitHash: string | ||
dataHash: string | ||
validatorsHash: string | ||
nextValidatorsHash: string | ||
consensusHash: string | ||
appHash: string | ||
lastResultsHash: string | ||
evidenceHash: string | ||
proposerAddress: string | ||
} | ||
|
||
/** Transaction in block. */ | ||
declare transactions: Transaction[] | ||
|
||
/** Responses from block API endpoints. */ | ||
|
||
static async fetchByHeight ( | ||
{ url, decode = Decode, chain }: { | ||
url: string|URL, decode?: typeof Decode, chain?: Namada | ||
}, | ||
{ height, raw }: { | ||
height: number|string|bigint, | ||
raw?: boolean, | ||
} | ||
): Promise<NamadaBlock> { | ||
if (!url) { | ||
throw new Error("Can't fetch block: missing connection URL") | ||
} | ||
// Fetch block and results as undecoded JSON | ||
const blockUrl = `${url}/block?height=${height}` | ||
const resultsUrl = `${url}/block_results?height=${height}` | ||
const [block, results] = await Promise.all([ | ||
fetch(blockUrl).then(response=>response.text()), | ||
fetch(resultsUrl).then(response=>response.text()), | ||
]) | ||
return this.fromResponses({ | ||
block: { url: blockUrl, response: block, }, | ||
results: { url: resultsUrl, response: results, }, | ||
}, { chain, decode, height }) | ||
} | ||
|
||
static async fetchByHash ( | ||
_1: { url: string|URL, decode?: typeof Decode, chain?: Namada }, | ||
_2: { hash: string, raw?: boolean }, | ||
): Promise<NamadaBlock> { | ||
throw new Error('NamadaBlock.fetchByHash: not implemented') | ||
} | ||
|
||
static fromResponses ( | ||
responses: NonNullable<NamadaBlock["responses"]>, | ||
{ decode = Decode, chain, height }: { | ||
decode?: typeof Decode | ||
chain?: Namada, | ||
height?: string|number|bigint | ||
}, | ||
): NamadaBlock { | ||
const { id, header, txs } = decode.block( | ||
responses.block.response, | ||
responses.results.response | ||
) as { | ||
id: string, | ||
txs: Partial<Transaction[]>[] | ||
header: NamadaBlock["header"] | ||
} | ||
|
||
return new NamadaBlock({ | ||
id, | ||
header, | ||
|
||
chain: chain!, | ||
height: Number(header.height), | ||
timestamp: header.time, | ||
|
||
transactions: txs.map((tx, i)=>{ | ||
try { | ||
return Transaction.fromDecoded({ | ||
height, | ||
...tx as any | ||
}) | ||
} catch (error) { | ||
console.error(error) | ||
console.warn(`Failed to decode transaction #${i} in block ${height}, see above for details.`) | ||
return new NamadaUndecodedTransaction({ | ||
error: error as any, | ||
data: tx as any, | ||
}) | ||
} | ||
}), | ||
|
||
responses | ||
}) | ||
|
||
} | ||
|
||
} |
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,139 @@ | ||
import * as CW from '@fadroma/cw' | ||
import type { ChainId } from '@hackbg/fadroma' | ||
import NamadaConnection from './NamadaConnection' | ||
import { Decode, initDecoder } from './NamadaDecode' | ||
|
||
export default class NamadaChain extends CW.Chain { | ||
decode = Decode | ||
|
||
/** Connect to Namada over one or more endpoints. */ | ||
static async connect ( | ||
properties: Parameters<typeof CW.Chain["connect"]>[0] & { | ||
chainId?: ChainId | ||
decoder?: string|URL|Uint8Array | ||
} | ||
): Promise<NamadaChain> { | ||
if (properties?.decoder) { | ||
await initDecoder(properties.decoder) | ||
} else { | ||
new CW.Console('@fadroma/namada').warn( | ||
"Decoder binary not provided; trying to decode Namada objects will fail." | ||
) | ||
} | ||
properties ??= {} as any | ||
properties.bech32Prefix ??= "tnam" | ||
return await super.connect(properties || ({} as any)) as NamadaChain | ||
} | ||
|
||
/** Connect to Namada using `testnetChainId` and `testnetURLs`. */ | ||
static testnet (properties: Parameters<typeof NamadaChain["connect"]>[0]) { | ||
return this.connect({ | ||
chainId: properties?.chainId || NamadaChain.testnetChainId, | ||
urls: (properties as any)?.url | ||
? [(properties as any).url] | ||
: ((properties as any)?.urls || [...NamadaChain.testnetURLs]), | ||
}) | ||
} | ||
|
||
/** Default chain ID of testnet. */ | ||
static testnetChainId = 'shielded-expedition.88f17d1d14' | ||
|
||
/** Default RPC endpoints for testnet. */ | ||
static testnetURLs = new Set([ | ||
'https://namada-testnet-rpc.itrocket.net', | ||
'https://namada-rpc.stake-machine.com', | ||
'https://namadarpc.songfi.xyz', | ||
'https://rpc.testnet.one', | ||
]) | ||
|
||
static get Connection () { | ||
return NamadaConnection | ||
} | ||
|
||
getConnection (): NamadaConnection { | ||
return this.connections[0] as NamadaConnection | ||
} | ||
|
||
authenticate (...args: unknown[]): never { | ||
throw new Error('Transacting on Namada is currently not supported.') | ||
} | ||
|
||
fetchPGFParameters () { | ||
return this.getConnection().fetchPGFParametersImpl() | ||
} | ||
|
||
fetchPGFStewards () { | ||
return this.getConnection().fetchPGFStewardsImpl() | ||
} | ||
|
||
fetchPGFFundings () { | ||
return this.getConnection().fetchPGFFundingsImpl() | ||
} | ||
|
||
isPGFSteward (address: string) { | ||
return this.getConnection().isPGFStewardImpl(address) | ||
} | ||
|
||
fetchStakingParameters () { | ||
return this.getConnection().fetchStakingParametersImpl() | ||
} | ||
|
||
fetchValidatorAddresses () { | ||
return this.getConnection().fetchValidatorAddressesImpl() | ||
} | ||
|
||
fetchValidator (address: string) { | ||
return this.getConnection().fetchValidatorImpl(address) | ||
} | ||
|
||
fetchValidators (options?: { | ||
details?: boolean, | ||
pagination?: [number, number] | ||
allStates?: boolean, | ||
addresses?: string[], | ||
parallel?: boolean, | ||
parallelDetails?: boolean, | ||
}) { | ||
return this.getConnection().fetchValidators(options) | ||
} | ||
|
||
fetchValidatorsConsensus () { | ||
return this.getConnection().fetchValidatorsConsensusImpl() | ||
} | ||
|
||
fetchValidatorsBelowCapacity () { | ||
return this.getConnection().fetchValidatorsBelowCapacityImpl() | ||
} | ||
|
||
fetchDelegations (address: string) { | ||
return this.getConnection().fetchDelegationsImpl(address) | ||
} | ||
|
||
fetchDelegationsAt (address: string, epoch?: number) { | ||
return this.getConnection().fetchDelegationsAtImpl(address, epoch) | ||
} | ||
|
||
fetchGovernanceParameters () { | ||
return this.getConnection().fetchGovernanceParametersImpl() | ||
} | ||
|
||
fetchProposalCount () { | ||
return this.getConnection().fetchProposalCountImpl() | ||
} | ||
|
||
fetchProposalInfo (id: number) { | ||
return this.getConnection().fetchProposalInfoImpl(id) | ||
} | ||
|
||
fetchCurrentEpoch () { | ||
return this.getConnection().fetchCurrentEpochImpl() | ||
} | ||
|
||
fetchTotalStaked () { | ||
return this.getConnection().fetchTotalStakedImpl() | ||
} | ||
|
||
fetchValidatorStake (address: string) { | ||
return this.getConnection().fetchValidatorStakeImpl(address) | ||
} | ||
} |
Oops, something went wrong.