Code samples
This sections contains different ParsiQL code samples

Ethereum

Uniswap Swap spikes

The following Smart-Trigger allows to monitor a defined Table of Uniswap Pair Pools, perform calculations and detect Swap spikes according to threshold.
In this example we observe the PRQ/ETH Pair's Pool and set the ETH (WETH to be precise) as the trading asset (TradingAsset) to set the thresholds against.

User Data

Table for storing Uniswap Pairs Pool data

Smart-Trigger

1
stream UniswapSwapSpikes
2
# We are interested in the Token Transfers for the Uniswap case.
3
from TokenTransfers
4
# We have a table with (interesting to us) Uniswap Pools. We want to monitor both BUYs and SELLs for them.
5
where @to in UniswapPools || @from in UniswapPools
6
process
7
​
8
# Basic initialization variable for later usage
9
let threshold = 0
10
let initiator = 0x0
11
let pool = 0x0
12
let action = ""
13
14
# If our Trading Asset is used for BUY operation
15
if @to in UniswapPools && @code_address == UniswapPools[@to].TradingAsset then
16
threshold = UniswapPools[@to].BuyThreshold
17
# The address that initiated the BUY operation
18
initiator = @from
19
# The pool that was
20
pool = @to
21
action = "BUY"
22
# If our Trading Asset is used for SELL operation
23
elseif @from in UniswapPools && @code_address == UniswapPools[@from].TradingAsset then
24
threshold = UniswapPools[@from].SellThreshold
25
initiator = @to
26
pool = @from
27
action = "SELL"
28
end
29
30
# Check that BUY or SELL happened
31
if action != "" then
32
# Additional check that we are dealing with ERC-20'ies
33
if @is_erc20 then
34
# We compare that the BUY/SELL amount is exceeding the defined (Buy/Sell)Threshold
35
if compare({value: @value, decimals: @erc20.decimals}, {value: threshold, decimals: 0}) >= 0 then
36
emit {@value, initiator, pool: UniswapPools[pool].Details, threshold, action, currency: @erc20.symbol, decimals: @erc20.decimals}
37
end
38
else
39
emit {@value, initiator, pool: UniswapPools[pool].Details, threshold, action, currency: "?", decimals: 18}
40
end
41
end
42
​
43
​
44
end
Copied!

Uniswap PRQ Spikes

This Smart-Trigger is a more simple and specific solution to the same task as in "Uniswap Swap spikes", only that it monitors Uniswap spikes specifically for PRQ/ETH Pair Pool against ETH (WETH to be precise)

User Data

Uniswap spike threshold values against PRQ and ETH separately
A Primitive Record to store WETH's Smart-Contract address
A Struct Record of fields that hold some PRQ related addresses

Smart-Trigger

1
stream PRQTransfers
2
from TokenTransfers
3
where @code_address == WETH && @to == PRQTrackingData.UniswapAddress
4
process
5
if compare({value: @value, decimals: @erc20.decimals}, {value: UniswapSpikeThreshold.ETH, decimals: 0}) >= 0 then
6
emit {@value, @to, @from, decimals: @erc20.decimals, current_spike_threshold: UniswapSpikeThreshold.ETH, currency: @erc20.symbol}
7
end
8
end
9
​
Copied!

PRQ Whale Transfers

The following ParsiQL code stands behind the Flashr (PRQ Project to be precise in this example) that is a sub-product of PARSIQ Monitoring and is completely based on the Public Project feature. It allows to monitor all PRQ TokenTransfers with a defined threshold that is large enough to be counted as a whale one.

User Data

Smart-Trigger

1
stream WhaleTransfers
2
from TokenTransfers
3
where @code_address == PRQ.ContractAddress
4
process
5
if compare({@value, decimals: @erc20.decimals}, {value: PRQ.WhaleTransferThreshold, decimals: 0}) >= 0 then
6
let description = "PARSIQ (" + @erc20.symbol + ") Whale Transfers"
7
8
let cryptorankFiatRate = getRate(@erc20.symbol)
9
let fiat_value = @value * cryptorankFiatRate.value
10
let fiat_decimals = @erc20.decimals + cryptorankFiatRate.decimals
11
12
emit {@to, @from, @value, decimals: @erc20.decimals, symbol: @erc20.symbol, description, fiat_value, fiat_decimals}
13
end
14
end
Copied!

PARSIQ Foundation Wallets monitoring

As with task in "PRQ Whale Transfers" - this one is also used behind Flashr and aims to monitor a set of PARSIQ Foundation Wallets.
Notice, that the stored User Data (for addresses table) is accessible via the public API for this particular Public Project

User Data

Smart-Trigger

1
stream FoundationTransfers
2
from TokenTransfers
3
where @code_address == PRQ.ContractAddress
4
where @to in addresses || @from in addresses
5
process
6
let toNote = ""
7
let fromNote = ""
8
​
9
if @to in addresses then
10
toNote = addresses[@to].label
11
fromNote = "origin"
12
else
13
toNote = "destination"
14
fromNote = addresses[@from].label
15
end
16
17
let description = "PARSIQ (" + @erc20.symbol + ") Foundation Transfers"
18
19
let cryptorankFiatRate = getRate(@erc20.symbol)
20
let fiat_value = @value * cryptorankFiatRate.value
21
let fiat_decimals = @erc20.decimals + cryptorankFiatRate.decimals
22
23
emit {@to, @from, toNote, fromNote, @value, decimals: @erc20.decimals, symbol: @erc20.symbol, description, fiat_value, fiat_decimals}
24
end
Copied!

Ocean Protocol Datatoken Accounting

This example shows how one can have multiple Datatokens and aggregate the volume of Datatokens used as a payment for specifc Dataset (matched against CorporateDatatokens Table Record) consumptions.

Smart-Trigger

1
stream CorporateDatasetAccounting
2
# Stream all possible Dataset consumes on the Ocean Protocol
3
from OceanDatasetConsumes
4
# Filter those that match our Datatokens
5
where @dataToken in CorporateDatatokens
6
process
7
# Initialize Datatoken volumes to 0
8
state labelledAnimalImagesDatatokenVolume = 0
9
state ebayProductsDatatokenVolume = 0
10
11
# Detect Dataset
12
let dataset = CorporateDatatokens[@dataToken].Dataset
13
let volumeToSendViaAPI = 0
14
15
if dataset == "Labelled Animal Images" then
16
# Update volume in case of first Dataset
17
labelledAnimalImagesDatatokenVolume += @amount
18
volumeToSendViaAPI = labelledAnimalImagesDatatokenVolume
19
# Emit results
20
emit {..., volumeToSendViaAPI, decimals: 18, dataset}
21
elseif dataset == "Ebay Products" then
22
# Update volume in case of second Dataset
23
ebayProductsDatatokenVolume += @amount
24
volumeToSendViaAPI = ebayProductsDatatokenVolume
25
# Emit results
26
emit {..., volumeToSendViaAPI, decimals: 18, dataset}
27
end
28
end
Copied!
In this example, specifically for ETH/USD pair.

Smart-Trigger

1
stream EthUsdPriceUpdates
2
from ChainlinkPriceFeed
3
where @pair == "ETH/USD"
4
process
5
let eth_usd_pair = getChainlinkPriceFeedPair("ETH/USD")
6
7
emit {..., eth_usd_pair}
8
end
Copied!

Compliance Wallet Tracker for CryptoPay

A Smart-Trigger that allows to set-up a multi-layer compliance protection for a fictional company, called "CryptoPay".

User Data

Smart-Trigger

1
# Our named Event Stream of "ClientTransfers"
2
stream ClientTransfers
3
# The Native Event Stream of ETH Transfers
4
from Transfers
5
# We are interested in deposits and withdrawals among our clients
6
where @to in ClientWallets || @from in ClientWallets
7
# We are interested in ETH Transfers that are more than our predefined MinimumTransfer
8
where compare({@value, decimals: 18}, {value: TrackingConfiguration.MinimumTransfer, decimals: 0}) > 0
9
process
10
# Accumulate IN- and OUT circulation volume among our clients
11
state totalInflow = 0
12
state totalOutflow = 0
13
14
# Our client address
15
let target = 0x0000000000000000000000000000000000000000
16
# Other party of transfer
17
let counterparty = 0x0000000000000000000000000000000000000000
18
19
if @to in ClientWallets then
20
totalInflow += @value
21
target = @to
22
counterparty = @from
23
elseif @from in ClientWallets then
24
totalOutflow += @value
25
target = @from
26
counterparty = @to
27
end
28
29
# Retrieve categorial risk score from Uppsala for non-client
30
let uppsalaRiskScore = getSentinelProtocolData("ETH", counterparty)
31
32
# 1st layer security. We start gathering more data in case of non-whitelisted result (greylist, blacklist or other)
33
if uppsalaRiskScore.securityCategory != "whitelist" then
34
# Retrieve numerical risk score from Crystal for non-client
35
let crystalRiskScore = getCrystalDataForETH(counterparty)
36
37
# 2nd layer security. We fire a compliance ALERT in case Crystal risk score is more than predefined AllowedRiskScore
38
if compare(crystalRiskScore.decimalRiskScore, {value: TrackingConfiguration.AllowedRiskScore, decimals: 2}) > 0 then
39
40
# Emit an ALERT
41
emit {type: "ALERT", @from, @to, @value, targetLabel: ClientWallets[target].Label, targetID: ClientWallets[target].ID}
42
else
43
# Just emit a NOTIFICATION
44
emit {type: "NOTIFICATION", @from, @to, @value, targetLabel: ClientWallets[target].Label, targetID: ClientWallets[target].ID}
45
end
46
else
47
# Just emit a NOTIFICATION
48
emit {type: "NOTIFICATION", @from, @to, @value, targetLabel: ClientWallets[target].Label, targetID: ClientWallets[target].ID}
49
end
50
51
​
52
end
Copied!

Binance Smart Chain

PancakeSwap volume aggregator for TWT/WBNB pair

In this particular case - we would like to aggregate the volume of TWT Tokens swapped in the context of TWT/WBNB Pair (BSC scan link) and then compare two approaches to calculating according USD volume: continuously or post factum.

User Data

Smart-Trigger

1
stream PancakeSwapTradesForTWTBNB
2
# We are interested in the BEP20 Token Transfers for the PancakeSwap case.
3
from BscBEP20Transfers
4
# We have a table with (interesting to us) PancakeSwap Pairs. We want to monitor both BUYs and SELLs for them.
5
where @to in PancakeSwapPairs || @from in PancakeSwapPairs
6
# Filter out everything except TWT/WBNB
7
where @to in PancakeSwapPairs && PancakeSwapPairs[@to].Pair == "TWT/WBNB" || @from in PancakeSwapPairs && PancakeSwapPairs[@from].Pair == "TWT/WBNB"
8
process
9
state startingBlock = 0
10
state buyVolumeTWT = 0
11
state sellVolumeTWT = 0
12
state buyVolumeInUSD = {value: 0, decimals: 0}
13
state sellVolumeInUSD = {value: 0, decimals: 0}
14
15
# Basic initialization variable for later usage
16
let initiator = 0x0
17
let pair = 0x0
18
let action = ""
19
let TWTinUSD = {value: 0, decimals: 0}
20
21
if startingBlock == 0 then
22
startingBlock = @block.number
23
end
24
25
let cryptorankPriceInUSDforTWT = {value: 0, decimals: 0}
26
27
if @token.symbol == "TWT" then
28
cryptorankPriceInUSDforTWT = getRate(@token.symbol)
29
TWTinUSD = {value: @value * cryptorankPriceInUSDforTWT.value, decimals: @token.decimals + cryptorankPriceInUSDforTWT.decimals}
30
end
31
32
# If our Trading Asset (TWT) is used in BUY operation
33
if @from in PancakeSwapPairs && @token.contract == PancakeSwapPairs[@from].PairFirst then
34
# The address that initiated the TWT BUY operation
35
initiator = @to
36
# The target Pair
37
pair = @from
38
# The action
39
action = "BUY"
40
# The according to operation TWT volume update
41
buyVolumeTWT += @value
42
# The according to operation USD volume update
43
buyVolumeInUSD = add(buyVolumeInUSD, TWTinUSD)
44
# If our Trading Asset (TWT) is used in SELL operation
45
elseif @to in PancakeSwapPairs && @token.contract == PancakeSwapPairs[@to].PairFirst then
46
initiator = @from
47
pair = @to
48
action = "SELL"
49
sellVolumeTWT += @value
50
sellVolumeInUSD = add(sellVolumeInUSD, TWTinUSD)
51
end
52
53
let convertedBuyVolumeInUSD = {value: buyVolumeTWT * cryptorankPriceInUSDforTWT.value, decimals: @token.decimals + cryptorankPriceInUSDforTWT.decimals}
54
let convertedSellVolumeInUSD = {value: sellVolumeTWT * cryptorankPriceInUSDforTWT.value, decimals: @token.decimals + cryptorankPriceInUSDforTWT.decimals}
55
56
# Check that BUY or SELL happened
57
if action == "BUY" || action == "SELL" then
58
emit {
59
@value,
60
decimals: @token.decimals,
61
symbol: @token.symbol,
62
initiator,
63
pair: PancakeSwapPairs[pair].Pair,
64
action,
65
blockNumber: @block.number,
66
buyVolumeTWT,
67
sellVolumeTWT,
68
buyVolumeInUSD,
69
sellVolumeInUSD,
70
convertedBuyVolumeInUSD,
71
convertedSellVolumeInUSD,
72
cryptorankPriceInUSDforTWT
73
}
74
end
75
76
77
end
78
​
Copied!
Last modified 9mo ago