diff --git a/data/testing__bridge_debridge_transfers.csv b/data/testing__bridge_debridge_transfers.csv new file mode 100644 index 00000000..62430a10 --- /dev/null +++ b/data/testing__bridge_debridge_transfers.csv @@ -0,0 +1,8 @@ +tx_id,program_id,direction,user_address,amount,mint +5QQhyhN51i34hwwA5GExb8QZ2QXvWyLJEyoh6F7CPReKbh2DPxEeek69z2rZqddkt844sBFfw7Jy7Uy8YoKM9qVs,dst5MGcFPoBeREFAA5E3tU5ij8m5uVYwkzkSAbsLbNo,inbound,EsWhiGGeKk3kjCKcEGQcr4KTksXMRyW8Zezz2ADfMpAT,0.001,So11111111111111111111111111111111111111112 +3ySH2GiuWxpXm4nH25Cc1n9MT3Zahdku2wzyve3E1hFeA83VV3AN7hWoWBp39Mtfyr6tHhwiSNeqMEkNn9a6aBEF,dst5MGcFPoBeREFAA5E3tU5ij8m5uVYwkzkSAbsLbNo,inbound,6cJP8jQ9mvgM6seScAK9ZtvrDkDm9c9zBZG5pASVfqcu,2.934814068,So11111111111111111111111111111111111111112 +4EP7wWKhma2dsi4mconqsWPCBM9ow4JaVRydxLEcrLwriaFEEgHu9uuJccqSb1o9pdF6wVdZq1tqvTjD9me4ciVc,src5qyZHqTqecJV4aY6Cb6zDZLMDzrDKKezs22MPHr4,outbound,6cJP8jQ9mvgM6seScAK9ZtvrDkDm9c9zBZG5pASVfqcu,37.665623,EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v +4sy3zM6EjNuZ65gFqfKUChRtVCQiHxedUhq8SSNEXJbckxHKExdig3zaJwSFNGTp9uYxLUHBWtr6maaGR1LAruMQ,src5qyZHqTqecJV4aY6Cb6zDZLMDzrDKKezs22MPHr4,outbound,CudPG9tCpYT3bRmWRNvAVKbH9bf8Xu3BEuRuNLWyY1uB,29.911008,EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v +4oUbo4UMmdpFsAd6mNtuN17ho43oLU5UYYR1mzKFmG5PRuKQMQnenEPkpS6S4RPWewqD2kBfB5wN92WEmMVV2bba,src5qyZHqTqecJV4aY6Cb6zDZLMDzrDKKezs22MPHr4,outbound,9Ro7iuqXYxHxKxkhPBNAZtrm1k19ugrFgSm8QXrcNvgt,59.424495,EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v +5g7jXMkPijbr2KxT9oGVm6MjjQ2xNP6EdYFuBJPuMj1x3jFC1AJ8VeMN9Wa9kho4D6ES7dcU8raVtynvLeSqm5dE,src5qyZHqTqecJV4aY6Cb6zDZLMDzrDKKezs22MPHr4,outbound,8FeSpL3QGwxQdx42qQJu1mPu1PMgBqewvRTSP2tFk96S,0.0000001,So11111111111111111111111111111111111111112 +1vZ9reeJ4JVYkxcmTEBjEeDn4nSb8FsWQqKBKCeQw7fh1EuM3UGrBUD7tBKPkX5Q3jGm1bCRG31gJePMW2Mjwfc,src5qyZHqTqecJV4aY6Cb6zDZLMDzrDKKezs22MPHr4,outbound,8FeSpL3QGwxQdx42qQJu1mPu1PMgBqewvRTSP2tFk96S,0.0001,EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v \ No newline at end of file diff --git a/data/testing__bridge_mayan_transfers.csv b/data/testing__bridge_mayan_transfers.csv new file mode 100644 index 00000000..fdc2f320 --- /dev/null +++ b/data/testing__bridge_mayan_transfers.csv @@ -0,0 +1,4 @@ +tx_id,program_id,direction,user_address,amount,mint +4qqEcftiXE4ug5dmEPNpqqJ2f82CYTYwmhVJRWTpwftrLxQTwQzGW8D6sWFbR7BxXjKfvuitHPUFJTME6B5cxiE8,8LPjGDbxhW4G2Q8S6FvdvUdfGWssgtqmvsc63bwNFA7E,inbound,9YFeuz8q9WMSJpeNhNHj6LSbZnQ6BvDt5u9CV2ALhPWv,4418582.24475,DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263 +4g5MiEFhfTWpctmWAS5Q435NxZxQWkTNQ22Lj7VVRx9BS6Tbeg8ACq7k25qN2EyUBG5eVFenqcSyFJKQgxFyud2Q,8LPjGDbxhW4G2Q8S6FvdvUdfGWssgtqmvsc63bwNFA7E,inbound,Az6gg8n9w57MSnT7tNeabY9xdAF6mxi94vcJk9MCWvav,0.572620188,So11111111111111111111111111111111111111112 +4AcYHm3GoS7efSHTXfsrPhmwFfeT9QASFraSeJHoJyZA3mpPfWuzeG9eyFKyn8ibW1dfCsuwfr3iFMx4GFTeBWHy,8LPjGDbxhW4G2Q8S6FvdvUdfGWssgtqmvsc63bwNFA7E,outbound,HGDcnZRSNRPLbWaGBsP2Pm7TMhwz2BafoL3UdFtnVvLv,25,EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v diff --git a/data/testing__bridge_wormhole_transfers.csv b/data/testing__bridge_wormhole_transfers.csv new file mode 100644 index 00000000..02d6e3ff --- /dev/null +++ b/data/testing__bridge_wormhole_transfers.csv @@ -0,0 +1,12 @@ +tx_id,program_id,direction,user_address,amount,mint +39QnQNLPgA8EfZdw6vbjQYdUhR9fb9Rw5K9EzJ7Br3S51yCY2NrSAi3YSM3F1rH6xYmvBE4oq9krSrjUvQGSrmzM,wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb,outbound,EadZ3ug2aPZtUiUUPJ5j86yAE1NGXuk3f9RMVY5191rx,0.2,So11111111111111111111111111111111111111112 +3FrmUUacSrahxpqzViWF9A3ZkvkgXvArnxmrCSD9UjtWBuduPFPtfTw7SxJDgBBrhBfUhfxZYnL16nr9jCgU7Pvt,wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb,inbound,BogfXtgPPJGQBALR5N23vQySPjCyRj4uj5MZpNvEfpRs,0.655723,7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs +faHTAkhRb1zs4nkwdvFMMCsnGi1ro3HrsAsqeq5kYPWaBsXo2ukFohPqE4ja1SYnFyEGAdSETAZZ3iMBDsbnhzH,wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb,inbound,BogfXtgPPJGQBALR5N23vQySPjCyRj4uj5MZpNvEfpRs,0.55,9gP2kCy3wA1ctvYWQk75guqXuHfrEomqydHLtcTCqiLa +38ZPcqmWfzkW47aUVBnYWehPFGHUtvRJrH4XrWLLUSnxvvXndMFcntCe297ppp6RHbmpgQNbEM3pTvCn4mEF7o1V,wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb,inbound,HZBb3y17RbkYk9wZfcoYMvGjyXcewichSyswgLVckVGg,0.175,7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs +2C6vZnTWkJ3FXJpW1zj18dfWKLGH26GWSHUr9j6Mpx7hwBdauWoDkE6B8ra54qRPN6BBw4PTsvW8ZqUtFRV3Bgdr,wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb,inbound,7dm9am6Qx7cH64RB99Mzf7ZsLbEfmXM7ihXXCvMiT2X1,822.062435,EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v +XtM25TbM8BW7L5JXoceVJoF41GuWMP69WjdxdWJUrKyYdV8DRXyGG81ey8JfRnS6UKYi67D2X3MYz1SCnVLvHmJ,wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb,inbound,GpLb588d4VDbJFSjTxQnaUXmWDw6swRcsT3rVvHMweAF,222.99939784,FCqfQSujuPxy6V42UvafBhsysWtEq1vhjfMN1PUbgaxA +1NSyLSuHwMmb7c6DSW5wsqf8B85i5tdTrXrw1dPS3eGL46EikLhZm6qbHUQRZReLkcuR7Es42xAidmk54N13FgC,wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb,inbound,7dm9am6Qx7cH64RB99Mzf7ZsLbEfmXM7ihXXCvMiT2X1,15.5,So11111111111111111111111111111111111111112 +1VFGjNWtmhTS6ahfvU5xxXHuQmMPF5bohEk5TEZyGsUrPRwEr92cz9UNtiY5scVsUtHUEFRu1mdqAoP4ydnCGVD,wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb,inbound,GKKnUx64Npy9FLcNPd58T4tNDTZUguiTZZuXwYetpdLg,999.496778,A9mUU4qviSctJVPJdBJWkb28deg915LYJKrzQ19ji3FM +3g7GGbBJpGDfCaa1MQVQGpieqYi6j9XWUtsUKXh6ogUi1ss7asthzd81irNrpx1WGW5h7B75FN7jhN4UCyicxgCe,wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb,inbound,7dm9am6Qx7cH64RB99Mzf7ZsLbEfmXM7ihXXCvMiT2X1,2.29999999,So11111111111111111111111111111111111111112 +2AzNhDD9GWUrJvhhrdCcaVnuU4Mb3aZKNozhCMJZJ52b9SwrQNg42JVmcx2GvfCxk6cKaPGdSz8gUWqqpaznRg3f,wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb,inbound,3dJzaZGHiWN3rffswvt4Vw1cvEmMXsMzRSGKkvGyRqKe,1000,9vMJfxuKxXBoEa7rM12mYLMwTacLMLDJqHozw96WQL8i +51bkYq62kFw9zX88KbbwBMGKeWgoNz7DXo8wU2aD6qbtL3LvvX2m58n6JS2HdYoUHmckHQkZMvnWA98aLQ1TAS29,wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb,outbound,9Ro7iuqXYxHxKxkhPBNAZtrm1k19ugrFgSm8QXrcNvgt,0.2,So11111111111111111111111111111111111111112 diff --git a/models/gold/defi/defi__fact_bridge_activity.sql b/models/gold/defi/defi__fact_bridge_activity.sql new file mode 100644 index 00000000..e60f3471 --- /dev/null +++ b/models/gold/defi/defi__fact_bridge_activity.sql @@ -0,0 +1,92 @@ +{{ config( + materialized = 'view', + meta ={ 'database_tags':{ 'table':{ 'PURPOSE': 'BRIDGE' }} }, + tags = ["scheduled_non_core"], +) }} + +SELECT + block_timestamp, + block_id, + tx_id, + succeeded, + INDEX, + program_id, + platform, + direction, + user_address, + amount, + mint, + COALESCE ( + bridge_wormhole_transfers_id, + {{ dbt_utils.generate_surrogate_key( + ['block_id','tx_id', 'index','direction'] + ) }} + ) AS fact_bridge_activity_id, + COALESCE( + inserted_timestamp, + '2000-01-01' + ) AS inserted_timestamp, + COALESCE( + modified_timestamp, + '2000-01-01' + ) AS modified_timestamp +FROM + {{ ref('silver__bridge_wormhole_transfers') }} +union all +SELECT + block_timestamp, + block_id, + tx_id, + succeeded, + INDEX, + program_id, + platform, + direction, + user_address, + amount, + mint, + COALESCE ( + bridge_debridge_transfers_id, + {{ dbt_utils.generate_surrogate_key( + ['block_id','tx_id', 'index'] + ) }} + ) AS fact_bridge_activity_id, + COALESCE( + inserted_timestamp, + '2000-01-01' + ) AS inserted_timestamp, + COALESCE( + modified_timestamp, + '2000-01-01' + ) AS modified_timestamp +FROM + {{ ref('silver__bridge_debridge_transfers') }} +union all +SELECT + block_timestamp, + block_id, + tx_id, + succeeded, + INDEX, + program_id, + platform, + direction, + user_address, + amount, + mint, + COALESCE ( + bridge_mayan_transfers_id, + {{ dbt_utils.generate_surrogate_key( + ['block_id','tx_id', 'index'] + ) }} + ) AS fact_bridge_activity_id, + COALESCE( + inserted_timestamp, + '2000-01-01' + ) AS inserted_timestamp, + COALESCE( + modified_timestamp, + '2000-01-01' + ) AS modified_timestamp +FROM + {{ ref('silver__bridge_mayan_transfers') }} diff --git a/models/gold/defi/defi__fact_bridge_activity.yml b/models/gold/defi/defi__fact_bridge_activity.yml new file mode 100644 index 00000000..d2226b51 --- /dev/null +++ b/models/gold/defi/defi__fact_bridge_activity.yml @@ -0,0 +1,51 @@ +version: 2 +models: + - name: defi__fact_bridge_activity + description: Table containing bridging actions on Wormhole, DeBridge and Mayan Finance + columns: + - name: BLOCK_TIMESTAMP + description: "{{ doc('block_timestamp') }}" + tests: + - dbt_expectations.expect_column_to_exist + - name: BLOCK_ID + description: "{{ doc('block_id') }}" + tests: + - dbt_expectations.expect_column_to_exist + - name: TX_ID + description: "{{ doc('tx_id') }}" + tests: + - dbt_expectations.expect_column_to_exist + - name: SUCCEEDED + description: "{{ doc('tx_succeeded') }}" + tests: + - dbt_expectations.expect_column_to_exist + - name: PROGRAM_ID + description: "{{ doc('program_id') }}" + tests: + - dbt_expectations.expect_column_to_exist + - name: PLATFORM + description: Name of the bridge protocol + tests: + - dbt_expectations.expect_column_to_exist + - name: DIRECTION + description: Direction of the bridge - either inbound to Solana or outbound from Solana + tests: + - dbt_expectations.expect_column_to_exist + - name: USER_ADDRESS + description: The address receiving or sending bridged tokens + tests: + - dbt_expectations.expect_column_to_exist + - name: AMOUNT + description: "{{ doc('amount') }}" + tests: + - dbt_expectations.expect_column_to_exist + - name: MINT + description: "{{ doc('mint') }}" + tests: + - dbt_expectations.expect_column_to_exist + - name: FACT_BRIDGE_ACTIVITY_ID + description: '{{ doc("pk") }}' + - name: INSERTED_TIMESTAMP + description: '{{ doc("inserted_timestamp") }}' + - name: MODIFIED_TIMESTAMP + description: '{{ doc("modified_timestamp") }}' \ No newline at end of file diff --git a/models/silver/bridges/silver__bridge_debridge_transfers.sql b/models/silver/bridges/silver__bridge_debridge_transfers.sql new file mode 100644 index 00000000..78f0c4da --- /dev/null +++ b/models/silver/bridges/silver__bridge_debridge_transfers.sql @@ -0,0 +1,201 @@ +{{ config( + materialized = 'incremental', + unique_key = ["block_id","tx_id","index"], + incremental_predicates = ['DBT_INTERNAL_DEST.block_timestamp::date >= LEAST(current_date-7,(select min(block_timestamp)::date from ' ~ generate_tmp_view_name(this) ~ '))'], + cluster_by = ['block_timestamp::DATE','_inserted_timestamp::DATE'], + tags = ['scheduled_non_core'] +) }} + +WITH base_events AS ( + + SELECT + * + FROM + {{ ref('silver__events') }} + WHERE + ( + program_id IN ( + 'dst5MGcFPoBeREFAA5E3tU5ij8m5uVYwkzkSAbsLbNo', + -- debridge in + 'src5qyZHqTqecJV4aY6Cb6zDZLMDzrDKKezs22MPHr4' -- debridge out + ) + OR ( + program_id = 'DEbrdGj3HsRsAzx6uH4MKyREKxVAfBydijLUF3ygsFfh' + AND ARRAY_CONTAINS( + 'src5qyZHqTqecJV4aY6Cb6zDZLMDzrDKKezs22MPHr4' :: variant, + inner_instruction_program_ids + ) + ) + ) + +{% if is_incremental() %} +AND _inserted_timestamp >= ( + SELECT + MAX(_inserted_timestamp) + FROM + {{ this }} +) +{% else %} + AND block_timestamp :: DATE >= '2022-12-14' +{% endif %} +), +base_transfers AS ( + SELECT + A.block_id, + A.block_timestamp, + A.tx_id, + A.succeeded, + A.program_id, + COALESCE(SPLIT_PART(A.index :: text, '.', 1) :: INT, A.index :: INT) AS INDEX, + NULLIF(SPLIT_PART(A.index :: text, '.', 2), '') :: INT AS inner_index, + A.tx_from, + A.tx_to, + A.amount, + A.mint, + b.program_id AS event_program_id, + A._inserted_timestamp + FROM + {{ ref('silver__transfers') }} A + INNER JOIN base_events b + ON A.tx_id = b.tx_id + WHERE + b.program_id IN ( + 'src5qyZHqTqecJV4aY6Cb6zDZLMDzrDKKezs22MPHr4', + 'dst5MGcFPoBeREFAA5E3tU5ij8m5uVYwkzkSAbsLbNo' + ) + +{% if is_incremental() %} +and + A._inserted_timestamp >= ( + SELECT + MAX(_inserted_timestamp) + FROM + {{ this }} + ) +{% else %} +and + A.block_timestamp :: DATE >= '2022-12-14' +{% endif %} +), +inbound AS ( + SELECT + A.block_timestamp, + A.block_id, + A.tx_id, + A.succeeded, + A.index, + A.program_id, + 'deBridge' AS platform, + 'inbound' AS direction, + tx_to AS user_address, + b.amount AS amount, + b.mint, + A._inserted_timestamp + FROM + base_events A + LEFT JOIN base_transfers b + ON A.tx_id = b.tx_id + AND A.index = b.index + AND A.signers [0] = A.instruction :accounts [1] :: STRING -- AND A.succeeded + WHERE + A.program_id = 'dst5MGcFPoBeREFAA5E3tU5ij8m5uVYwkzkSAbsLbNo' + AND b.mint IS NOT NULL + AND A.instruction :accounts [6] :: STRING = 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA' +), +outbound AS ( + SELECT + A.block_timestamp, + A.block_id, + A.tx_id, + A.succeeded, + A.index, + A.program_id, + 'deBridge' AS platform, + 'outbound' AS direction, + tx_from AS user_address, + tx_to AS temp_receiver, + b.amount AS amount, + b.mint, + A._inserted_timestamp + FROM + base_events A + LEFT JOIN base_transfers b + ON A.tx_id = b.tx_id + AND A.index = b.index + WHERE + A.program_id = 'src5qyZHqTqecJV4aY6Cb6zDZLMDzrDKKezs22MPHr4' + AND amount != 0.01735944 + AND b.program_id <> '11111111111111111111111111111111' + qualify ROW_NUMBER() over ( + PARTITION BY A.tx_id + ORDER BY + A.index + ) = 1 +), +cancel_bridging AS ( -- bridging can be cancelled after initial outbound tx + SELECT + block_timestamp, + tx_id, + instruction :accounts [28] :: STRING AS returner, + instruction :accounts [30] :: STRING AS canceler + FROM + base_events + WHERE + program_id = 'DEbrdGj3HsRsAzx6uH4MKyREKxVAfBydijLUF3ygsFfh' +), +outbound_fulfilled AS ( + SELECT + A.* + FROM + outbound A + LEFT JOIN cancel_bridging b + ON A.user_address = b.canceler + AND A.temp_receiver = b.returner + and a.block_timestamp < b.block_timestamp + WHERE + b.tx_id IS NULL + +) +SELECT + block_timestamp, + block_id, + tx_id, + succeeded, + INDEX, + program_id, + platform, + direction, + user_address, + amount, + mint, + _inserted_timestamp, + {{ dbt_utils.generate_surrogate_key( + ['block_id','tx_id', 'index'] + ) }} AS bridge_debridge_transfers_id, + SYSDATE() AS inserted_timestamp, + SYSDATE() AS modified_timestamp, + '{{ invocation_id }}' AS _invocation_id +FROM + outbound_fulfilled +UNION ALL +SELECT + block_timestamp, + block_id, + tx_id, + succeeded, + INDEX, + program_id, + platform, + direction, + user_address, + amount, + mint, + _inserted_timestamp, + {{ dbt_utils.generate_surrogate_key( + ['block_id','tx_id', 'index'] + ) }} AS bridge_debridge_transfers_id, + SYSDATE() AS inserted_timestamp, + SYSDATE() AS modified_timestamp, + '{{ invocation_id }}' AS _invocation_id +FROM + inbound diff --git a/models/silver/bridges/silver__bridge_debridge_transfers.yml b/models/silver/bridges/silver__bridge_debridge_transfers.yml new file mode 100644 index 00000000..eb55d4a7 --- /dev/null +++ b/models/silver/bridges/silver__bridge_debridge_transfers.yml @@ -0,0 +1,71 @@ +version: 2 +models: + - name: silver__bridge_debridge_transfers + tests: + - dbt_utils.unique_combination_of_columns: + combination_of_columns: + - BRIDGE_DEBRIDGE_TRANSFERS_ID + - compare_model_subset: + name: silver__bridge_debridge_transfers_logic_test + compare_model: ref('testing__bridge_debridge_transfers') + compare_columns: + - tx_id + - program_id + - direction + - user_address + - round(amount,8) + - mint + model_condition: "where tx_id in ('5QQhyhN51i34hwwA5GExb8QZ2QXvWyLJEyoh6F7CPReKbh2DPxEeek69z2rZqddkt844sBFfw7Jy7Uy8YoKM9qVs', + '3ySH2GiuWxpXm4nH25Cc1n9MT3Zahdku2wzyve3E1hFeA83VV3AN7hWoWBp39Mtfyr6tHhwiSNeqMEkNn9a6aBEF', + '4EP7wWKhma2dsi4mconqsWPCBM9ow4JaVRydxLEcrLwriaFEEgHu9uuJccqSb1o9pdF6wVdZq1tqvTjD9me4ciVc', + '4sy3zM6EjNuZ65gFqfKUChRtVCQiHxedUhq8SSNEXJbckxHKExdig3zaJwSFNGTp9uYxLUHBWtr6maaGR1LAruMQ', + '4oUbo4UMmdpFsAd6mNtuN17ho43oLU5UYYR1mzKFmG5PRuKQMQnenEPkpS6S4RPWewqD2kBfB5wN92WEmMVV2bba', + '5g7jXMkPijbr2KxT9oGVm6MjjQ2xNP6EdYFuBJPuMj1x3jFC1AJ8VeMN9Wa9kho4D6ES7dcU8raVtynvLeSqm5dE', + '1vZ9reeJ4JVYkxcmTEBjEeDn4nSb8FsWQqKBKCeQw7fh1EuM3UGrBUD7tBKPkX5Q3jGm1bCRG31gJePMW2Mjwfc')" + columns: + - name: BLOCK_TIMESTAMP + description: "{{ doc('block_timestamp') }}" + tests: + - dbt_expectations.expect_row_values_to_have_recent_data: + datepart: day + interval: 2 + - name: BLOCK_ID + description: "{{ doc('block_id') }}" + tests: + - not_null + - name: TX_ID + description: "{{ doc('tx_id') }}" + tests: + - not_null + - name: SUCCEEDED + description: "{{ doc('tx_succeeded') }}" + tests: + - not_null + - name: PROGRAM_ID + description: "{{ doc('program_id') }}" + tests: + - not_null + - name: PLATFORM + description: Name of the bridge + tests: + - not_null + - name: DIRECTION + description: Direction of the bridge - either inbound to Solana or outbound from Solana + tests: + - not_null + - name: USER_ADDRESS + description: The address receiving or sending bridged tokens + tests: + - not_null + - name: AMOUNT + description: "{{ doc('amount') }}" + tests: + - not_null + - name: MINT + description: "{{ doc('mint') }}" + tests: + - not_null + - name: _INSERTED_TIMESTAMP + description: "{{ doc('tx_id') }}" + tests: + - not_null diff --git a/models/silver/bridges/silver__bridge_mayan_transfers.sql b/models/silver/bridges/silver__bridge_mayan_transfers.sql new file mode 100644 index 00000000..54361933 --- /dev/null +++ b/models/silver/bridges/silver__bridge_mayan_transfers.sql @@ -0,0 +1,130 @@ +{{ config( + materialized = 'incremental', + unique_key = ["block_id","tx_id","index"], + incremental_predicates = ['DBT_INTERNAL_DEST.block_timestamp::date >= LEAST(current_date-7,(select min(block_timestamp)::date from ' ~ generate_tmp_view_name(this) ~ '))'], + cluster_by = ['block_timestamp::DATE','_inserted_timestamp::DATE'], + tags = ['scheduled_non_core'] +) }} + +WITH base_events AS ( + + SELECT + * + FROM + {{ ref('silver__events') }} + WHERE + program_id = '8LPjGDbxhW4G2Q8S6FvdvUdfGWssgtqmvsc63bwNFA7E' + +{% if is_incremental() %} +AND _inserted_timestamp >= ( + SELECT + MAX(_inserted_timestamp) + FROM + {{ this }} +) +{% else %} + AND block_timestamp :: DATE >= '2022-09-19' +{% endif %} +), +base_transfers AS ( + SELECT + A.block_id, + A.block_timestamp, + A.tx_id, + A.succeeded, + A.program_id, + COALESCE(SPLIT_PART(A.index :: text, '.', 1) :: INT, A.index :: INT) AS INDEX, + NULLIF(SPLIT_PART(A.index :: text, '.', 2), '') :: INT AS inner_index, + A.tx_from, + A.tx_to, + A.amount, + A.mint, + b.program_id AS event_program_id, + A._inserted_timestamp + FROM + {{ ref('silver__transfers') }} A + INNER JOIN base_events b + ON A.tx_id = b.tx_id + +{% if is_incremental() %} +WHERE + A._inserted_timestamp >= ( + SELECT + MAX(_inserted_timestamp) + FROM + {{ this }} + ) +{% else %} +WHERE + A.block_timestamp :: DATE >= '2022-09-19' +{% endif %} +), +outbound_mayan AS ( + SELECT + A.block_timestamp, + A.block_id, + A.tx_id, + A.succeeded, + A.index, + A.program_id, + 'mayan finance' AS platform, + 'outbound' AS direction, + b.tx_from AS user_address, + b.amount, + b.mint, + A._inserted_timestamp + FROM + base_events A + LEFT JOIN base_transfers b + ON A.tx_id = b.tx_id + AND A.index = b.index + WHERE + b.tx_to = '5yZiE74sGLCT4uRoyeqz4iTYiUwX5uykiPRggCVih9PN' + AND A.instruction :accounts [11] :: STRING = '11111111111111111111111111111111' +), +inbound_mayan AS ( + SELECT + A.block_timestamp, + A.block_id, + A.tx_id, + A.succeeded, + A.index, + A.program_id, + 'mayan finance' AS platform, + 'inbound' AS direction, + b.tx_to AS user_address, + b.amount, + b.mint, + A._inserted_timestamp + FROM + base_events A + LEFT JOIN base_transfers b + ON A.tx_id = b.tx_id + AND A.index = b.index + WHERE + b.tx_from = '5yZiE74sGLCT4uRoyeqz4iTYiUwX5uykiPRggCVih9PN' + AND NOT b.tx_to = '7dm9am6Qx7cH64RB99Mzf7ZsLbEfmXM7ihXXCvMiT2X1' + AND A.instruction :accounts [9] :: STRING = 'SysvarC1ock11111111111111111111111111111111' + AND A.instruction :accounts [10] :: STRING = 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA' +), +pre_final AS ( + SELECT + * + FROM + inbound_mayan + UNION ALL + SELECT + * + FROM + outbound_mayan +) +SELECT + *, + {{ dbt_utils.generate_surrogate_key( + ['block_id','tx_id', 'index'] + ) }} AS bridge_mayan_transfers_id, + SYSDATE() AS inserted_timestamp, + SYSDATE() AS modified_timestamp, + '{{ invocation_id }}' AS _invocation_id +FROM + pre_final diff --git a/models/silver/bridges/silver__bridge_mayan_transfers.yml b/models/silver/bridges/silver__bridge_mayan_transfers.yml new file mode 100644 index 00000000..70451c53 --- /dev/null +++ b/models/silver/bridges/silver__bridge_mayan_transfers.yml @@ -0,0 +1,67 @@ +version: 2 +models: + - name: silver__bridge_mayan_transfers + tests: + - dbt_utils.unique_combination_of_columns: + combination_of_columns: + - BRIDGE_MAYAN_TRANSFERS_ID + - compare_model_subset: + name: silver__bridge_mayan_transfers_logic_test + compare_model: ref('testing__bridge_mayan_transfers') + compare_columns: + - tx_id + - program_id + - direction + - user_address + - round(amount,8) + - mint + model_condition: "where tx_id in ('4qqEcftiXE4ug5dmEPNpqqJ2f82CYTYwmhVJRWTpwftrLxQTwQzGW8D6sWFbR7BxXjKfvuitHPUFJTME6B5cxiE8', + '4g5MiEFhfTWpctmWAS5Q435NxZxQWkTNQ22Lj7VVRx9BS6Tbeg8ACq7k25qN2EyUBG5eVFenqcSyFJKQgxFyud2Q', + '4AcYHm3GoS7efSHTXfsrPhmwFfeT9QASFraSeJHoJyZA3mpPfWuzeG9eyFKyn8ibW1dfCsuwfr3iFMx4GFTeBWHy')" + columns: + - name: BLOCK_TIMESTAMP + description: "{{ doc('block_timestamp') }}" + tests: + - dbt_expectations.expect_row_values_to_have_recent_data: + datepart: day + interval: 2 + - name: BLOCK_ID + description: "{{ doc('block_id') }}" + tests: + - not_null + - name: TX_ID + description: "{{ doc('tx_id') }}" + tests: + - not_null + - name: SUCCEEDED + description: "{{ doc('tx_succeeded') }}" + tests: + - not_null + - name: PROGRAM_ID + description: "{{ doc('program_id') }}" + tests: + - not_null + - name: PLATFORM + description: Name of the bridge + tests: + - not_null + - name: DIRECTION + description: Direction of the bridge - either inbound to Solana or outbound from Solana + tests: + - not_null + - name: USER_ADDRESS + description: The address receiving or sending bridged tokens + tests: + - not_null + - name: AMOUNT + description: "{{ doc('amount') }}" + tests: + - not_null + - name: MINT + description: "{{ doc('mint') }}" + tests: + - not_null + - name: _INSERTED_TIMESTAMP + description: "{{ doc('tx_id') }}" + tests: + - not_null diff --git a/models/silver/bridges/silver__bridge_wormhole_transfers.sql b/models/silver/bridges/silver__bridge_wormhole_transfers.sql new file mode 100644 index 00000000..847246aa --- /dev/null +++ b/models/silver/bridges/silver__bridge_wormhole_transfers.sql @@ -0,0 +1,253 @@ +{{ config( + materialized = 'incremental', + unique_key = ["block_id","tx_id","index","direction"], + incremental_predicates = ['DBT_INTERNAL_DEST.block_timestamp::date >= LEAST(current_date-7,(select min(block_timestamp)::date from ' ~ generate_tmp_view_name(this) ~ '))'], + cluster_by = ['block_timestamp::DATE','_inserted_timestamp::DATE'], + tags = ['scheduled_non_core'] +) }} + +WITH base_events AS ( + + SELECT + * + FROM + {{ ref('silver__events') }} + WHERE + ( + program_id = 'wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb' + OR ( + ARRAY_CONTAINS( + 'wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb' :: variant, + inner_instruction_program_ids + ) + AND program_id <> '8LPjGDbxhW4G2Q8S6FvdvUdfGWssgtqmvsc63bwNFA7E' -- exclude mayan bridge tx's + ) + ) + +{% if is_incremental() %} +AND _inserted_timestamp >= ( + SELECT + MAX(_inserted_timestamp) + FROM + {{ this }} +) +{% else %} + AND block_timestamp :: DATE >= '2021-09-13' +{% endif %} +), +wormhole_events AS ( + SELECT + block_timestamp, + block_id, + tx_id, + succeeded, + signers, + INDEX, + NULL AS inner_index, + program_id, + instruction, + _inserted_timestamp + FROM + base_events + WHERE + program_id = 'wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb' + UNION ALL + SELECT + e.block_timestamp, + e.block_id, + e.tx_id, + e.succeeded, + e.signers, + e.index, + i.index AS inner_index, + i.value :programId :: STRING AS program_id, + i.value AS instruction, + e._inserted_timestamp + FROM + base_events e, + TABLE(FLATTEN(e.inner_instruction :instructions)) i + WHERE + e.program_id <> 'wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb' + AND i.value :programId :: STRING = 'wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb' +), +base_transfers AS ( + SELECT + A.block_id, + A.block_timestamp, + A.tx_id, + A.succeeded, + A.program_id, + COALESCE(SPLIT_PART(A.index :: text, '.', 1) :: INT, A.index :: INT) AS INDEX, + NULLIF(SPLIT_PART(A.index :: text, '.', 2), '') :: INT AS inner_index, + A.tx_from, + A.tx_to, + A.amount, + A.mint, + b.program_id AS event_program_id, + A._inserted_timestamp + FROM + {{ ref('silver__transfers') }} A + INNER JOIN base_events b + ON A.tx_id = b.tx_id + +{% if is_incremental() %} +WHERE + A._inserted_timestamp >= ( + SELECT + MAX(_inserted_timestamp) + FROM + {{ this }} + ) +{% else %} +WHERE + A.block_timestamp :: DATE >= '2021-09-13' +{% endif %} +), +wormhole_transfers AS ( + SELECT + A.block_timestamp, + A.block_id, + A.tx_id, + A.succeeded, + A.index, + A.program_id, + 'wormhole' AS platform, + CASE + WHEN b.tx_from = 'GugU1tP7doLeTw9hQP51xRJyS8Da1fWxuiy2rVrnMD2m' THEN 'inbound' + ELSE 'outbound' + END AS direction, + A.signers [0] :: STRING AS user_address, + b.mint, + A._inserted_timestamp, + SUM( + b.amount + ) AS amount + FROM + wormhole_events A + INNER JOIN base_transfers b USING(tx_id) + WHERE + b.amount > 0 + AND ( + b.tx_from = 'GugU1tP7doLeTw9hQP51xRJyS8Da1fWxuiy2rVrnMD2m' + OR b.tx_to = 'GugU1tP7doLeTw9hQP51xRJyS8Da1fWxuiy2rVrnMD2m' + ) + AND A.program_id = 'wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb' + GROUP BY + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11 +), +inbound AS ( + SELECT + A.block_timestamp, + A.block_id, + A.tx_id, + A.succeeded, + b.index, + b.program_id, + 'wormhole' AS platform, + 'inbound' AS direction, + b.signers [0] :: STRING AS user_address, + A.mint, + A._inserted_timestamp, + A.mint_amount / pow( + 10, + A.decimal + ) AS amount + FROM + solana.silver.token_mint_actions A + INNER JOIN wormhole_events b USING(tx_id) + WHERE + succeeded + AND A.mint_amount > 0 + AND ( + ( + b.inner_index IS NULL + AND b.program_id = 'wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb' + ) + OR ( + b.inner_index IS NOT NULL + AND b.program_id = 'wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb' + ) + ) + AND b.instruction :accounts [5] = A.token_account + qualify ROW_NUMBER() over ( + PARTITION BY A.tx_id + ORDER BY + A.index, + A.inner_index + ) = 1 +), +outbound AS ( + SELECT + A.block_timestamp, + A.block_id, + A.tx_id, + A.succeeded, + b.index, + b.program_id, + 'wormhole' AS platform, + 'outbound' AS direction, + b.signers [0] :: STRING AS user_address, + A.mint, + A._inserted_timestamp, + A.burn_amount / pow( + 10, + A.decimal + ) AS amount + FROM + solana.silver.token_burn_actions A + INNER JOIN wormhole_events b USING(tx_id) + WHERE + succeeded + AND A.burn_amount > 0 + AND ( + ( + b.inner_index IS NULL + AND b.program_id = 'wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb' + ) + OR ( + b.inner_index IS NOT NULL + AND b.program_id = 'wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb' + ) + ) qualify ROW_NUMBER() over ( + PARTITION BY A.tx_id + ORDER BY + A.index, + A.inner_index + ) = 1 +), +pre_final AS ( + SELECT + * + FROM + wormhole_transfers + UNION ALL + SELECT + * + FROM + inbound + UNION ALL + SELECT + * + FROM + outbound +) +SELECT + *, + {{ dbt_utils.generate_surrogate_key( + ['block_id','tx_id', 'index','direction'] + ) }} AS bridge_wormhole_transfers_id, + SYSDATE() AS inserted_timestamp, + SYSDATE() AS modified_timestamp, + '{{ invocation_id }}' AS _invocation_id +FROM + pre_final diff --git a/models/silver/bridges/silver__bridge_wormhole_transfers.yml b/models/silver/bridges/silver__bridge_wormhole_transfers.yml new file mode 100644 index 00000000..b3a163e7 --- /dev/null +++ b/models/silver/bridges/silver__bridge_wormhole_transfers.yml @@ -0,0 +1,76 @@ +version: 2 +models: + - name: silver__bridge_wormhole_transfers + tests: + - dbt_utils.unique_combination_of_columns: + combination_of_columns: + - BRIDGE_WORMHOLE_TRANSFERS_ID + - compare_model_subset: + name: silver__bridge_wormhole_transfers_logic_test + compare_model: ref('testing__bridge_wormhole_transfers') + compare_columns: + - tx_id + - program_id + - direction + - user_address + - round(amount,8) + - mint + model_condition: "where tx_id in ( + '39QnQNLPgA8EfZdw6vbjQYdUhR9fb9Rw5K9EzJ7Br3S51yCY2NrSAi3YSM3F1rH6xYmvBE4oq9krSrjUvQGSrmzM', + '3FrmUUacSrahxpqzViWF9A3ZkvkgXvArnxmrCSD9UjtWBuduPFPtfTw7SxJDgBBrhBfUhfxZYnL16nr9jCgU7Pvt', + 'faHTAkhRb1zs4nkwdvFMMCsnGi1ro3HrsAsqeq5kYPWaBsXo2ukFohPqE4ja1SYnFyEGAdSETAZZ3iMBDsbnhzH', + '38ZPcqmWfzkW47aUVBnYWehPFGHUtvRJrH4XrWLLUSnxvvXndMFcntCe297ppp6RHbmpgQNbEM3pTvCn4mEF7o1V', + '2C6vZnTWkJ3FXJpW1zj18dfWKLGH26GWSHUr9j6Mpx7hwBdauWoDkE6B8ra54qRPN6BBw4PTsvW8ZqUtFRV3Bgdr', + 'XtM25TbM8BW7L5JXoceVJoF41GuWMP69WjdxdWJUrKyYdV8DRXyGG81ey8JfRnS6UKYi67D2X3MYz1SCnVLvHmJ', + '1NSyLSuHwMmb7c6DSW5wsqf8B85i5tdTrXrw1dPS3eGL46EikLhZm6qbHUQRZReLkcuR7Es42xAidmk54N13FgC', + '1VFGjNWtmhTS6ahfvU5xxXHuQmMPF5bohEk5TEZyGsUrPRwEr92cz9UNtiY5scVsUtHUEFRu1mdqAoP4ydnCGVD', + '3g7GGbBJpGDfCaa1MQVQGpieqYi6j9XWUtsUKXh6ogUi1ss7asthzd81irNrpx1WGW5h7B75FN7jhN4UCyicxgCe', + '2AzNhDD9GWUrJvhhrdCcaVnuU4Mb3aZKNozhCMJZJ52b9SwrQNg42JVmcx2GvfCxk6cKaPGdSz8gUWqqpaznRg3f', + '51bkYq62kFw9zX88KbbwBMGKeWgoNz7DXo8wU2aD6qbtL3LvvX2m58n6JS2HdYoUHmckHQkZMvnWA98aLQ1TAS29')" + columns: + - name: BLOCK_TIMESTAMP + description: "{{ doc('block_timestamp') }}" + tests: + - dbt_expectations.expect_row_values_to_have_recent_data: + datepart: day + interval: 2 + - name: BLOCK_ID + description: "{{ doc('block_id') }}" + tests: + - not_null + - name: TX_ID + description: "{{ doc('tx_id') }}" + tests: + - not_null + - name: SUCCEEDED + description: "{{ doc('tx_succeeded') }}" + tests: + - not_null + - name: PROGRAM_ID + description: "{{ doc('program_id') }}" + tests: + - not_null + - name: PLATFORM + description: Name of the bridge + tests: + - not_null + - name: DIRECTION + description: Direction of the bridge - either inbound to Solana or outbound from Solana + tests: + - not_null + - name: USER_ADDRESS + description: The address receiving or sending bridged tokens + tests: + - not_null + - name: AMOUNT + description: "{{ doc('amount') }}" + tests: + - not_null + - name: MINT + description: "{{ doc('mint') }}" + tests: + - not_null + - name: _INSERTED_TIMESTAMP + description: "{{ doc('tx_id') }}" + tests: + - not_null