-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Order Processing e2e tests * progress * common functions * purchase region * untested * support any os * fix typo * fix * readme * improve logging * progress * works :) * fixes * refund surplus * temporary solution * fix psvm * cleanup tests * resolve todo & format * fixes * last touches
- Loading branch information
Showing
21 changed files
with
616 additions
and
349 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
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
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
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,51 @@ | ||
import { ApiPromise } from '@polkadot/api'; | ||
import { KeyringPair } from '@polkadot/keyring/types'; | ||
import { RegionId } from 'coretime-utils'; | ||
import { submitExtrinsic } from './common'; | ||
import { CONFIG, CORE_COUNT, INITIAL_PRICE } from './consts'; | ||
|
||
async function configureBroker(coretimeApi: ApiPromise, signer: KeyringPair): Promise<void> { | ||
const configCall = coretimeApi.tx.broker.configure(CONFIG); | ||
const sudo = coretimeApi.tx.sudo.sudo(configCall); | ||
return submitExtrinsic(signer, sudo, {}); | ||
} | ||
|
||
async function startSales(coretimeApi: ApiPromise, signer: KeyringPair): Promise<void> { | ||
const startSaleCall = coretimeApi.tx.broker.startSales(INITIAL_PRICE, CORE_COUNT); | ||
const sudo = coretimeApi.tx.sudo.sudo(startSaleCall); | ||
return submitExtrinsic(signer, sudo, {}); | ||
} | ||
|
||
async function purchaseRegion( | ||
coretimeApi: ApiPromise, | ||
buyer: KeyringPair | ||
): Promise<RegionId | null> { | ||
const callTx = async (resolve: (regionId: RegionId | null) => void) => { | ||
const purchase = coretimeApi.tx.broker.purchase(INITIAL_PRICE * 10n); | ||
const unsub = await purchase.signAndSend(buyer, async (result: any) => { | ||
if (result.status.isInBlock) { | ||
const regionId = await getRegionId(coretimeApi); | ||
unsub(); | ||
resolve(regionId); | ||
} | ||
}); | ||
}; | ||
|
||
return new Promise(callTx); | ||
} | ||
|
||
async function getRegionId(coretimeApi: ApiPromise): Promise<RegionId | null> { | ||
const events: any = await coretimeApi.query.system.events(); | ||
|
||
for (const record of events) { | ||
const { event } = record; | ||
if (event.section === 'broker' && event.method === 'Purchased') { | ||
const data = event.data[1].toHuman(); | ||
return data; | ||
} | ||
} | ||
|
||
return null; | ||
} | ||
|
||
export { configureBroker, startSales, purchaseRegion }; |
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,89 @@ | ||
import { ApiPromise } from '@polkadot/api'; | ||
import { KeyringPair } from '@polkadot/keyring/types'; | ||
import { ISubmittableResult } from '@polkadot/types/types'; | ||
import { submitExtrinsic } from './common'; | ||
import { Get, IsmpRequest } from './types'; | ||
|
||
async function ismpAddParachain(signer: KeyringPair, regionXApi: ApiPromise) { | ||
const addParaCall = regionXApi.tx.ismpParachain.addParachain([1005]); | ||
const sudoCall = regionXApi.tx.sudo.sudo(addParaCall); | ||
return submitExtrinsic(signer, sudoCall, {}); | ||
} | ||
|
||
async function queryRequest(regionxApi: ApiPromise, commitment: string): Promise<IsmpRequest> { | ||
const leafIndex = regionxApi.createType('LeafIndexQuery', { commitment }); | ||
const requests = await (regionxApi as any).rpc.ismp.queryRequests([leafIndex]); | ||
// We only requested a single request so we only get one in the response. | ||
return requests.toJSON()[0] as IsmpRequest; | ||
} | ||
|
||
async function makeIsmpResponse( | ||
regionXApi: ApiPromise, | ||
coretimeApi: ApiPromise, | ||
request: IsmpRequest, | ||
responderAddress: string | ||
): Promise<void> { | ||
if (isGetRequest(request)) { | ||
const hashAt = ( | ||
await coretimeApi.query.system.blockHash(Number(request.get.height)) | ||
).toString(); | ||
const proofData = await coretimeApi.rpc.state.getReadProof([request.get.keys[0]], hashAt); | ||
|
||
const stateMachineProof = regionXApi.createType('StateMachineProof', { | ||
hasher: 'Blake2', | ||
storage_proof: proofData.proof, | ||
}); | ||
|
||
const substrateStateProof = regionXApi.createType('SubstrateStateProof', { | ||
StateProof: stateMachineProof, | ||
}); | ||
const response = regionXApi.tx.ismp.handleUnsigned([ | ||
{ | ||
Response: { | ||
datagram: { | ||
Request: [request], | ||
}, | ||
proof: { | ||
height: { | ||
id: { | ||
stateId: { | ||
Kusama: 1005, | ||
}, | ||
consensusStateId: 'PARA', | ||
}, | ||
height: request.get.height.toString(), | ||
}, | ||
proof: substrateStateProof.toHex(), | ||
}, | ||
signer: responderAddress, | ||
}, | ||
}, | ||
]); | ||
|
||
return new Promise((resolve, reject) => { | ||
const unsub = response.send((result: ISubmittableResult) => { | ||
const { status, isError } = result; | ||
console.log(`Current status is ${status}`); | ||
if (status.isInBlock) { | ||
console.log(`Transaction included at blockHash ${status.asInBlock}`); | ||
} else if (status.isFinalized) { | ||
console.log(`Transaction finalized at blockHash ${status.asFinalized}`); | ||
unsub.then(); | ||
return resolve(); | ||
} else if (isError) { | ||
console.log('Transaction error'); | ||
unsub.then(); | ||
return reject(); | ||
} | ||
}); | ||
}); | ||
} else { | ||
new Error('Expected a Get request'); | ||
} | ||
} | ||
|
||
const isGetRequest = (request: IsmpRequest): request is { get: Get } => { | ||
return (request as { get: Get }).get !== undefined; | ||
}; | ||
|
||
export { makeIsmpResponse, queryRequest, ismpAddParachain }; |
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,107 @@ | ||
import { ApiPromise, Keyring, WsProvider } from '@polkadot/api'; | ||
import assert from 'node:assert'; | ||
import { | ||
log, | ||
openHrmpChannel, | ||
RELAY_ASSET_ID, | ||
setupRelayAsset, | ||
sleep, | ||
submitExtrinsic, | ||
transferRelayAssetToPara, | ||
} from '../common'; | ||
import { UNIT } from '../consts'; | ||
import { configureBroker, purchaseRegion, startSales } from '../coretime.common'; | ||
import { ismpAddParachain } from '../ismp.common'; | ||
import { REGIONX_API_TYPES, REGIONX_CUSTOM_RPC } from '../types'; | ||
import { transferRegionToRegionX } from '../xc-regions.common'; | ||
|
||
async function run(_nodeName: string, networkInfo: any, _jsArgs: any) { | ||
const { wsUri: regionXUri } = networkInfo.nodesByName['regionx-collator01']; | ||
const { wsUri: coretimeUri } = networkInfo.nodesByName['coretime-collator01']; | ||
const { wsUri: rococoUri } = networkInfo.nodesByName['rococo-validator01']; | ||
|
||
const regionXApi = await ApiPromise.create({ | ||
provider: new WsProvider(regionXUri), | ||
types: { ...REGIONX_API_TYPES }, | ||
rpc: REGIONX_CUSTOM_RPC, | ||
}); | ||
const rococoApi = await ApiPromise.create({ provider: new WsProvider(rococoUri) }); | ||
const coretimeApi = await ApiPromise.create({ provider: new WsProvider(coretimeUri) }); | ||
|
||
// account to submit tx | ||
const keyring = new Keyring({ type: 'sr25519' }); | ||
const alice = keyring.addFromUri('//Alice'); | ||
const bob = keyring.addFromUri('//Bob'); | ||
|
||
const txSetRelayXcmVersion = rococoApi.tx.xcmPallet.forceDefaultXcmVersion([3]); | ||
const txSetCoretimeXcmVersion = coretimeApi.tx.polkadotXcm.forceDefaultXcmVersion([3]); | ||
log('Setting XCM version: '); | ||
await submitExtrinsic(alice, rococoApi.tx.sudo.sudo(txSetRelayXcmVersion), {}); | ||
await submitExtrinsic(alice, coretimeApi.tx.sudo.sudo(txSetCoretimeXcmVersion), {}); | ||
|
||
log('Setting up relay asset: '); | ||
await setupRelayAsset(regionXApi, alice, 500n * UNIT); | ||
|
||
log('Opening HRMP: '); | ||
await openHrmpChannel(alice, rococoApi, 1005, 2000); | ||
await openHrmpChannel(alice, rococoApi, 2000, 1005); | ||
log('Adding ISMP: '); | ||
await ismpAddParachain(alice, regionXApi); | ||
|
||
log('Transfering rc token to RegionX:'); | ||
await transferRelayAssetToPara(rococoApi, alice, 1005, alice.address, 100n * UNIT); | ||
await transferRelayAssetToPara(rococoApi, alice, 2000, alice.address, 100n * UNIT); | ||
|
||
log('Configuring coretime chain:'); | ||
await configureBroker(coretimeApi, alice); | ||
log('Starting sales:'); | ||
await startSales(coretimeApi, alice); | ||
|
||
const regionId = await purchaseRegion(coretimeApi, alice); | ||
if (!regionId) throw new Error('RegionId not found'); | ||
|
||
log('Transferring region to RegionX'); | ||
await transferRegionToRegionX(coretimeApi, regionXApi, alice, regionId); | ||
|
||
const paraId = 2000; | ||
const orderRequirements = { | ||
begin: 40, | ||
end: 45, | ||
coreOccupancy: 57600, // full core | ||
}; | ||
|
||
log('Creating order'); | ||
const createOrderCall = regionXApi.tx.orders.createOrder(paraId, orderRequirements); | ||
await submitExtrinsic(alice, createOrderCall, {}); | ||
|
||
const order = (await regionXApi.query.orders.orders(0)).toJSON(); | ||
assert.deepStrictEqual(order, { | ||
creator: alice.address, | ||
paraId: 2000, | ||
requirements: orderRequirements, | ||
}); | ||
|
||
log('Giving Bob tokens'); | ||
const transferToBobCall = regionXApi.tx.tokens.transfer(bob.address, RELAY_ASSET_ID, 30n * UNIT); | ||
await submitExtrinsic(alice, regionXApi.tx.sudo.sudo(transferToBobCall), {}); | ||
|
||
log('Bob making a contribution'); | ||
const contributeCall = regionXApi.tx.orders.contribute(0, 10n * UNIT); | ||
await submitExtrinsic(bob, contributeCall, {}); | ||
|
||
log('Alice fulfilling the order'); | ||
const fulfillCall = regionXApi.tx.processor.fulfillOrder(0, regionId); | ||
await submitExtrinsic(alice, fulfillCall, {}); | ||
// Region should be removed after making the assignment call: | ||
const regions = await regionXApi.query.regions.regions.entries(); | ||
assert.equal(regions.length, 0); | ||
|
||
// `fulfillOrder` will make a cross-chain call to the Coretime chain to make the assignment. | ||
// We will wait a bit since it will take some time. | ||
await sleep(5000); | ||
|
||
const workplan = await coretimeApi.query.broker.workplan.entries(); | ||
assert.equal(workplan.length, 1); | ||
} | ||
|
||
export { run }; |
File renamed without changes.
Oops, something went wrong.