Skip to content

Commit

Permalink
Update deploy branch (#69)
Browse files Browse the repository at this point in the history
* add statemine

Signed-off-by: Stepan Lavrentev <lawrentievsv@gmail.com>

* fix constraint

* ISSUE-51: Assets transfer history

* NOVA_3665: switch <action>.multi to multiQuery (#40)

* ISSUE-39: Fee calculation with withdraw (#42)

* Update polkadot api

* Check erasStakersClipped exists

* Update readme and package name

* Set extrinsic hash as optional

* Custom asset transfer

* fix deploy branch

* fix

* Transform assetTransfer to jsonfield

* upgrade polkadot/api to 7

* fix schema

* rename

* update workflows

* Fix for assettransfer checking

* add more networks in list

* add tests for promote to prod

* add new networks

* Prepare to pull request to deploy branch

Co-authored-by: Stepan Lavrentev <lawrentievsv@gmail.com>
Co-authored-by: asmadek <alma2610@ya.ru>
Co-authored-by: Stepan Lavrentev <40560660+stepanLav@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
  • Loading branch information
4 people authored Mar 25, 2022
1 parent 9e00d8b commit f8f5f8a
Show file tree
Hide file tree
Showing 83 changed files with 16,304 additions and 576 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/push_to_deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
chain: [acala, altair, astar, basilisk, bifrost, bit-country, calamari, centrifuge, clover, crab, edgeware]
chain: [acala, altair, astar, basilisk, bifrost, bit-country, calamari, centrifuge, clover, crab, edgeware, karura, statemine]

steps:
- uses: actions/checkout@v2
Expand Down
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,9 @@ src/types
.data
.idea
.DS_Store
yarn.lock
yarn.lock
.venv
.vscode
__pycache__
temporary
.pytest_cache
11 changes: 11 additions & 0 deletions networks/acala/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@ type Transfer @jsonField {
success: Boolean!
}

type AssetTransfer @jsonField {
assetId: String!
amount: String!
to: String!
from: String!
fee: String!
eventIdx: Int!
success: Boolean!
}

type Reward @jsonField {
eventIdx: Int!
amount: String!
Expand Down Expand Up @@ -40,6 +50,7 @@ type HistoryElement @entity {
reward: Reward
extrinsic: Extrinsic
transfer: Transfer
assetTransfer: AssetTransfer
}

type EraValidatorInfo @entity {
Expand Down
115 changes: 72 additions & 43 deletions networks/acala/src/mappings/HistoryElements.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import {SubstrateExtrinsic} from '@subql/types';
import {HistoryElement, Transfer} from "../types";
import {AssetTransfer, HistoryElement, Transfer} from "../types";
import {
callFromProxy, callsFromBatch,
calculateFeeAsString,
extrinsicIdFromBlockAndIdx, isBatch, isProxy,
isTransfer,
timestamp
timestamp,
isAssetTransfer,
isOrmlTransfer
} from "./common";
import {CallBase} from "@polkadot/types/types/calls";
import {AnyTuple} from "@polkadot/types/types/codec";
Expand All @@ -23,46 +25,44 @@ export async function handleHistoryElement(extrinsic: SubstrateExtrinsic): Promi
}
}

async function saveFailedTransfers(transfers: Transfer[], extrinsic: SubstrateExtrinsic): Promise<void> {
function createHistoryElement (extrinsic: SubstrateExtrinsic, address: string, suffix: string = '') {
let extrinsicHash = extrinsic.extrinsic.hash.toString();
let blockNumber = extrinsic.block.block.header.number.toNumber();
let extrinsicIdx = extrinsic.idx
let extrinsicId = extrinsicIdFromBlockAndIdx(blockNumber, extrinsicIdx)
let blockTimestamp = timestamp(extrinsic.block);

const historyElement = new HistoryElement(`${extrinsicId}${suffix}`);
historyElement.address = address
historyElement.blockNumber = blockNumber
historyElement.extrinsicHash = extrinsicHash
historyElement.extrinsicIdx = extrinsicIdx
historyElement.timestamp = blockTimestamp

return historyElement
}

async function saveFailedTransfers(transfers: Array<Transfer | AssetTransfer>, extrinsic: SubstrateExtrinsic): Promise<void> {
let promises = transfers.map(transfer => {
let extrinsicHash = extrinsic.extrinsic.hash.toString();
let blockNumber = extrinsic.block.block.header.number.toNumber();
let extrinsicIdx = extrinsic.idx
let extrinsicId = extrinsicIdFromBlockAndIdx(blockNumber, extrinsicIdx)
let blockTimestamp = timestamp(extrinsic.block);

const elementFrom = new HistoryElement(extrinsicId+`-from`);
elementFrom.address = transfer.from
elementFrom.blockNumber = blockNumber
elementFrom.extrinsicHash = extrinsicHash
elementFrom.extrinsicIdx = extrinsicIdx
elementFrom.timestamp = blockTimestamp
elementFrom.transfer = transfer

const elementTo = new HistoryElement(extrinsicId+`-to`);
elementTo.address = transfer.to
elementTo.blockNumber = blockNumber
elementTo.extrinsicHash = extrinsicHash
elementTo.extrinsicIdx = extrinsicIdx
elementTo.timestamp = blockTimestamp
elementTo.transfer = transfer
const elementFrom = createHistoryElement(extrinsic, transfer.from, `-from`);
const elementTo = createHistoryElement(extrinsic, transfer.to, `-to`);

if ('assetId' in transfer) {
elementFrom.assetTransfer = transfer
elementTo.assetTransfer = transfer
} else {
elementFrom.transfer = transfer
elementTo.transfer = transfer
}

return [elementTo.save(), elementFrom.save()]
})
await Promise.allSettled(promises)
}

async function saveExtrinsic(extrinsic: SubstrateExtrinsic): Promise<void> {
let blockNumber = extrinsic.block.block.header.number.toNumber();
let extrinsicIdx = extrinsic.idx
let extrinsicId = extrinsicIdFromBlockAndIdx(blockNumber, extrinsicIdx)
async function saveExtrinsic(extrinsic: SubstrateExtrinsic): Promise<void> {
const element = createHistoryElement(extrinsic, extrinsic.extrinsic.signer.toString())

const element = new HistoryElement(extrinsicId);
element.address = extrinsic.extrinsic.signer.toString()
element.blockNumber = blockNumber
element.extrinsicHash = extrinsic.extrinsic.hash.toString()
element.extrinsicIdx = extrinsicIdx
element.timestamp = timestamp(extrinsic.block)
element.extrinsic = {
hash: extrinsic.extrinsic.hash.toString(),
module: extrinsic.extrinsic.method.section,
Expand All @@ -74,7 +74,7 @@ async function saveExtrinsic(extrinsic: SubstrateExtrinsic): Promise<void> {
}

/// Success Transfer emits Transfer event that is handled at Transfers.ts handleTransfer()
function findFailedTransferCalls(extrinsic: SubstrateExtrinsic): Transfer[] | null {
function findFailedTransferCalls(extrinsic: SubstrateExtrinsic): Array<Transfer | AssetTransfer> | null {
if (extrinsic.success) {
return null;
}
Expand All @@ -85,24 +85,31 @@ function findFailedTransferCalls(extrinsic: SubstrateExtrinsic): Transfer[] | nu
}

let sender = extrinsic.extrinsic.signer
return transferCallsArgs.map(tuple => {
let blockNumber = extrinsic.block.block.header.number.toNumber();
return {
extrinsicHash: extrinsic.extrinsic.hash.toString(),
amount: tuple[1].toString(),
return transferCallsArgs.map(([address, amount, assetId]) => {
const transfer: Transfer = {
amount: amount.toString(),
from: sender.toString(),
to: tuple[0],
blockNumber: blockNumber,
to: address,
fee: calculateFeeAsString(extrinsic),
eventIdx: -1,
success: false
}

if (assetId) {
(transfer as AssetTransfer).assetId = assetId
}

return transfer;
})
}

function determineTransferCallsArgs(causeCall: CallBase<AnyTuple>) : [string, bigint][] {
function determineTransferCallsArgs(causeCall: CallBase<AnyTuple>) : [string, bigint, string?][] {
if (isTransfer(causeCall)) {
return [extractArgsFromTransfer(causeCall)]
} else if (isAssetTransfer(causeCall)) {
return [extractArgsFromAssetTransfer(causeCall)]
} else if (isOrmlTransfer(causeCall)) {
return [extractArgsFromOrmlTransfer(causeCall)]
} else if (isBatch(causeCall)) {
return callsFromBatch(causeCall)
.map(call => {
Expand All @@ -125,3 +132,25 @@ function extractArgsFromTransfer(call: CallBase<AnyTuple>): [string, bigint] {

return [destinationAddress.toString(), (amount as u64).toBigInt()]
}

function extractArgsFromAssetTransfer(call: CallBase<AnyTuple>): [string, bigint, string] {
const [assetId, destinationAddress, amount] = call.args

return [
destinationAddress.toString(),
(amount as u64).toBigInt(),
assetId.toString()
]
}

function extractArgsFromOrmlTransfer(call: CallBase<AnyTuple>): [string, bigint, string] {
const [destinationAddress, currencyId, amount] = call.args

return [
destinationAddress.toString(),
(amount as u64).toBigInt(),
currencyId.toHex().toString()
]
}


14 changes: 11 additions & 3 deletions networks/acala/src/mappings/Transfers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,15 +111,23 @@ async function createTransfer({
element.extrinsicIdx = event.extrinsic.idx;
}

element.transfer = {
assetId,
const transfer = {
amount: amount.toString(),
from: from.toString(),
to: to.toString(),
fee: calculateFeeAsString(event.extrinsic),
eventIdx: event.idx,
success: true,
};
}

if (assetId) {
element.assetTransfer = {
...transfer,
assetId: assetId,
};
} else {
element.transfer = transfer
}

await element.save();
}
11 changes: 10 additions & 1 deletion networks/acala/src/mappings/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import {AnyTuple} from "@polkadot/types/types/codec";
import { Vec, GenericEventData } from '@polkadot/types';

const batchCalls = ["batch", "batchAll"]
const transferCalls = ["transfer", "transferKeepAlive"]
const transferCalls = ["transfer", "transferKeepAlive", "transferAll"]
const ormlSections = ["currencies", "tokens"]

export function distinct<T>(array: Array<T>): Array<T> {
return [...new Set(array)];
Expand All @@ -24,6 +25,14 @@ export function isTransfer(call: CallBase<AnyTuple>) : boolean {
return call.section == "balances" && transferCalls.includes(call.method)
}

export function isAssetTransfer(call: CallBase<AnyTuple>) : boolean {
return call.section == "assets" && transferCalls.includes(call.method)
}

export function isOrmlTransfer(call: CallBase<AnyTuple>) : boolean {
return ormlSections.includes(call.section) && transferCalls.includes(call.method)
}

export function callsFromBatch(batchCall: CallBase<AnyTuple>) : CallBase<AnyTuple>[] {
return batchCall.args[0] as Vec<CallBase<AnyTuple>>
}
Expand Down
11 changes: 11 additions & 0 deletions networks/altair/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@ type Transfer @jsonField {
success: Boolean!
}

type AssetTransfer @jsonField {
assetId: String!
amount: String!
to: String!
from: String!
fee: String!
eventIdx: Int!
success: Boolean!
}

type Reward @jsonField {
eventIdx: Int!
amount: String!
Expand Down Expand Up @@ -40,6 +50,7 @@ type HistoryElement @entity {
reward: Reward
extrinsic: Extrinsic
transfer: Transfer
assetTransfer: AssetTransfer
}

type EraValidatorInfo @entity {
Expand Down
Loading

0 comments on commit f8f5f8a

Please sign in to comment.