-
Notifications
You must be signed in to change notification settings - Fork 104
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'bridge-next-gen' into ron/polkadot-assets-on-ethereum
- Loading branch information
Showing
46 changed files
with
16,242 additions
and
3,404 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,61 @@ | ||
name: npm-publish | ||
|
||
on: | ||
release: | ||
types: [published] | ||
|
||
env: | ||
NPM_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }} | ||
|
||
jobs: | ||
publish: | ||
runs-on: snowbridge-runner | ||
timeout-minutes: 15 | ||
steps: | ||
- name: Checkout | ||
uses: actions/checkout@v4 | ||
with: | ||
fetch-depth: 2 | ||
|
||
- name: Install Foundry | ||
uses: foundry-rs/foundry-toolchain@v1 | ||
|
||
- name: Build Contracts | ||
working-directory: contracts | ||
run: | | ||
forge build | ||
- name: Install Node.js | ||
uses: actions/setup-node@v4 | ||
with: | ||
node-version: '20.x' | ||
registry-url: 'https://registry.npmjs.org' | ||
|
||
- name: Install pnpm | ||
uses: pnpm/action-setup@v3 | ||
with: | ||
version: 8 | ||
|
||
- name: Build Contract Types | ||
working-directory: web/packages/contract-types | ||
run: | | ||
pnpm install | ||
pnpm typechain | ||
pnpm build | ||
- name: Build API | ||
working-directory: web/packages/api | ||
run: | | ||
pnpm install | ||
pnpm build | ||
- name: Publish Contract Types | ||
working-directory: web/packages/contract-types | ||
run: | | ||
pnpm publish | ||
- name: Publish API | ||
working-directory: web/packages/api | ||
run: | | ||
pnpm publish | ||
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 +1,4 @@ | ||
store-dir=.pnpm-store/ | ||
//registry.npmjs.org/:_authToken=${NPM_AUTH_TOKEN} | ||
always-auth=false | ||
access=public |
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
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,63 +1,131 @@ | ||
// import "@polkadot/api-augment/polkadot" | ||
import { ApiPromise, WsProvider } from "@polkadot/api" | ||
import { ethers } from "ethers" | ||
import { IGateway, IGateway__factory } from "@snowbridge/contract-types" | ||
// import '@polkadot/api-augment/polkadot' | ||
import { ApiPromise, WsProvider } from '@polkadot/api' | ||
import { ethers } from 'ethers' | ||
import { BeefyClient, BeefyClient__factory, IGateway, IGateway__factory } from '@snowbridge/contract-types' | ||
|
||
interface Config { | ||
ethereum: { | ||
url: string | ||
} | ||
polkadot: { | ||
url: string | ||
url: { | ||
bridgeHub: string | ||
assetHub: string | ||
relaychain: string | ||
parachains?: string[] | ||
} | ||
} | ||
appContracts: { | ||
gateway: string | ||
beefy: string | ||
} | ||
} | ||
|
||
interface AppContracts { | ||
gateway: IGateway | ||
beefyClient: BeefyClient | ||
} | ||
|
||
class Context { | ||
export class Context { | ||
config: Config | ||
ethereum: EthereumContext | ||
polkadot: PolkadotContext | ||
|
||
constructor(ethereum: EthereumContext, polkadot: PolkadotContext) { | ||
constructor(config: Config, ethereum: EthereumContext, polkadot: PolkadotContext) { | ||
this.config = config | ||
this.ethereum = ethereum | ||
this.polkadot = polkadot | ||
} | ||
} | ||
|
||
class EthereumContext { | ||
api: ethers.providers.WebSocketProvider | ||
api: ethers.WebSocketProvider | ||
contracts: AppContracts | ||
|
||
constructor(api: ethers.providers.WebSocketProvider, contracts: AppContracts) { | ||
constructor(api: ethers.WebSocketProvider, contracts: AppContracts) { | ||
this.api = api | ||
this.contracts = contracts | ||
} | ||
} | ||
|
||
class PolkadotContext { | ||
api: ApiPromise | ||
constructor(api: ApiPromise) { | ||
this.api = api | ||
api: { | ||
relaychain: ApiPromise | ||
assetHub: ApiPromise | ||
bridgeHub: ApiPromise | ||
parachains: { [paraId: number]: ApiPromise } | ||
} | ||
constructor(relaychain: ApiPromise, assetHub: ApiPromise, bridgeHub: ApiPromise) { | ||
this.api = { | ||
relaychain: relaychain, | ||
assetHub: assetHub, | ||
bridgeHub: bridgeHub, | ||
parachains: {} | ||
} | ||
} | ||
} | ||
|
||
// eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
const contextFactory = async (config: Config): Promise<Context> => { | ||
let ethApi = new ethers.providers.WebSocketProvider(config.ethereum.url) | ||
let polApi = await ApiPromise.create({ | ||
provider: new WsProvider(config.polkadot.url), | ||
export const contextFactory = async (config: Config): Promise<Context> => { | ||
const ethApi = new ethers.WebSocketProvider(config.ethereum.url) | ||
const relaychainApi = await ApiPromise.create({ | ||
provider: new WsProvider(config.polkadot.url.relaychain), | ||
}) | ||
const assetHubApi = await ApiPromise.create({ | ||
provider: new WsProvider(config.polkadot.url.assetHub), | ||
}) | ||
const bridgeHubApi = await ApiPromise.create({ | ||
provider: new WsProvider(config.polkadot.url.bridgeHub), | ||
}) | ||
|
||
let gatewayAddr = process.env["GatewayProxyAddress"]! | ||
const gatewayAddr = config.appContracts.gateway | ||
const beefyAddr = config.appContracts.beefy | ||
|
||
let appContracts: AppContracts = { | ||
const appContracts: AppContracts = { | ||
//TODO: Get gateway address from bridgehub | ||
gateway: IGateway__factory.connect(gatewayAddr, ethApi), | ||
//TODO: Get beefy client from gateway | ||
beefyClient: BeefyClient__factory.connect(beefyAddr, ethApi), | ||
} | ||
|
||
let ethCtx = new EthereumContext(ethApi, appContracts) | ||
let polCtx = new PolkadotContext(polApi) | ||
const ethCtx = new EthereumContext(ethApi, appContracts) | ||
const polCtx = new PolkadotContext(relaychainApi, assetHubApi, bridgeHubApi) | ||
|
||
return new Context(ethCtx, polCtx) | ||
const context = new Context(config, ethCtx, polCtx) | ||
for (const parachain of config.polkadot.url.parachains ?? []) { | ||
await addParachainConnection(context, parachain) | ||
} | ||
return context | ||
} | ||
|
||
export const addParachainConnection = async (context: Context, url: string): Promise<void> => { | ||
const api = await ApiPromise.create({ | ||
provider: new WsProvider(url) | ||
}) | ||
const paraId = (await api.query.parachainInfo.parachainId()).toPrimitive() as number | ||
if (paraId in context.polkadot.api.parachains) { | ||
throw new Error(`${paraId} already added.`) | ||
} | ||
context.polkadot.api.parachains[paraId] = api | ||
console.log(`${url} added with parachain id: ${paraId}`) | ||
} | ||
|
||
export const destroyContext = async (context: Context): Promise<void> => { | ||
// clean up etheruem | ||
await context.ethereum.contracts.beefyClient.removeAllListeners() | ||
await context.ethereum.contracts.gateway.removeAllListeners() | ||
await context.ethereum.api.destroy() | ||
// clean up polkadot | ||
await context.polkadot.api.relaychain.disconnect() | ||
await context.polkadot.api.bridgeHub.disconnect() | ||
await context.polkadot.api.assetHub.disconnect() | ||
|
||
for (const paraId of Object.keys(context.polkadot.api.parachains)) { | ||
await context.polkadot.api.parachains[Number(paraId)].disconnect() | ||
} | ||
} | ||
|
||
export * as toPolkadot from './toPolkadot' | ||
export * as toEthereum from './toEthereum' | ||
export * as utils from './utils' | ||
export * as status from './status' |
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,52 @@ | ||
import { ApiPromise } from '@polkadot/api' | ||
import { Codec } from '@polkadot/types/types' | ||
import { filter, firstValueFrom, take } from 'rxjs' | ||
|
||
export const waitForMessageQueuePallet = async ( | ||
parachain: ApiPromise, | ||
messageId: string | undefined, | ||
siblingParachain: number, | ||
eventFilter: (event: Codec) => boolean, | ||
options = { | ||
scanBlocks: 10, | ||
} | ||
): Promise<{ foundEvent?: Codec, allEvents: Codec, extrinsicSuccess: boolean }> => { | ||
let extrinsicSuccess = false | ||
let returnEvent = undefined | ||
let receivedEvents = await firstValueFrom( | ||
parachain.rx.query.system.events().pipe( | ||
take(options.scanBlocks), | ||
filter(events => { | ||
let foundMessageQueue = false | ||
let foundEvent = false | ||
for (const event of (events as any)) { | ||
let eventData = event.event.toPrimitive().data | ||
if (parachain.events.messageQueue.Processed.is(event.event) | ||
// TODO: Use SetTopic to forward the message id to the destination chain and then remove undefined check. | ||
&& (messageId === undefined || eventData[0].toLowerCase() === messageId.toLowerCase()) | ||
&& eventData[1]?.sibling === siblingParachain) { | ||
|
||
foundMessageQueue = true | ||
extrinsicSuccess = eventData[3] | ||
} | ||
|
||
if (eventFilter(event)) { | ||
foundEvent = true | ||
returnEvent = event | ||
} | ||
} | ||
return foundMessageQueue && ((extrinsicSuccess && foundEvent) || !extrinsicSuccess) | ||
}), | ||
), | ||
{ defaultValue: undefined } | ||
) | ||
|
||
if (receivedEvents === undefined) { | ||
throw Error('Timeout while waiting for event.') | ||
} | ||
return { | ||
foundEvent: returnEvent, | ||
allEvents: receivedEvents, | ||
extrinsicSuccess: extrinsicSuccess | ||
} | ||
} |
Oops, something went wrong.