tx-indexer 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{classification.types-w82k4B1F.d.ts → classification.types-DlJe6bDZ.d.ts} +2 -6
- package/dist/{client-BS9KUBU7.d.ts → client-yGDWPKKf.d.ts} +6 -81
- package/dist/client.d.ts +2 -2
- package/dist/client.js +395 -255
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +12 -12
- package/dist/index.js +395 -255
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -149,6 +149,7 @@ function extractProgramIds(transaction) {
|
|
|
149
149
|
var SYSTEM_PROGRAM_ID = "11111111111111111111111111111111";
|
|
150
150
|
var COMPUTE_BUDGET_PROGRAM_ID = "ComputeBudget111111111111111111111111111111";
|
|
151
151
|
var STAKE_PROGRAM_ID = "Stake11111111111111111111111111111111111111";
|
|
152
|
+
var STAKE_POOL_PROGRAM_ID = "SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy";
|
|
152
153
|
var TOKEN_PROGRAM_ID = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA";
|
|
153
154
|
var ASSOCIATED_TOKEN_PROGRAM_ID = "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL";
|
|
154
155
|
var SPL_MEMO_PROGRAM_ID = "MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr";
|
|
@@ -158,6 +159,15 @@ var JUPITER_V4_PROGRAM_ID = "JUP4Fb2cqiRUcaTHdrPC8h2gNsA2ETXiPDD33WcGuJB";
|
|
|
158
159
|
var RAYDIUM_PROGRAM_ID = "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8";
|
|
159
160
|
var ORCA_WHIRLPOOL_PROGRAM_ID = "whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc";
|
|
160
161
|
var METAPLEX_PROGRAM_ID = "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s";
|
|
162
|
+
var CANDY_MACHINE_V3_PROGRAM_ID = "CndyV3LdqHUfDLmE5naZjVN8rBZz4tqhdefbAnjHG3JR";
|
|
163
|
+
var CANDY_GUARD_PROGRAM_ID = "Guard1JwRhJkVH6XZhzoYxeBVQe872VH6QggF4BWmS9g";
|
|
164
|
+
var BUBBLEGUM_PROGRAM_ID = "BGUMAp9Gq7iTEuizy4pqaxsTyUCBK68MDfK752saRPUY";
|
|
165
|
+
var MAGIC_EDEN_CANDY_MACHINE_ID = "CMZYPASGWeTz7RNGHaRJfCq2XQ5pYK6nDvVQxzkH51zb";
|
|
166
|
+
var WORMHOLE_PROGRAM_ID = "worm2ZoG2kUd4vFXhvjh93UUH596ayRfgQ2MgjNMTth";
|
|
167
|
+
var WORMHOLE_TOKEN_BRIDGE_ID = "wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb";
|
|
168
|
+
var DEGODS_BRIDGE_PROGRAM_ID = "35iLrpYNNR9ygHLcvE1xKFHbHq6paHthrF6wSovdWgGu";
|
|
169
|
+
var DEBRIDGE_PROGRAM_ID = "DEbrdGj3HsRsAzx6uH4MKyREKxVAfBydijLUF3ygsFfh";
|
|
170
|
+
var ALLBRIDGE_PROGRAM_ID = "BrdgN2RPzEMWF96ZbnnJaUtQDQx7VRXYaHHbYCBvceWB";
|
|
161
171
|
var PAYAI_FACILITATOR = "2wKupLR9q6wXYppw8Gr2NvWxKBUqm4PPJKkQfoxHDBg4";
|
|
162
172
|
var KNOWN_FACILITATORS = [
|
|
163
173
|
PAYAI_FACILITATOR
|
|
@@ -600,7 +610,7 @@ var DEX_PROTOCOL_IDS = /* @__PURE__ */ new Set([
|
|
|
600
610
|
function isDexProtocol(protocol) {
|
|
601
611
|
return protocol !== null && protocol !== void 0 && DEX_PROTOCOL_IDS.has(protocol.id);
|
|
602
612
|
}
|
|
603
|
-
function transactionToLegs(tx
|
|
613
|
+
function transactionToLegs(tx) {
|
|
604
614
|
const legs = [];
|
|
605
615
|
const feePayer = tx.accountKeys?.[0]?.toLowerCase();
|
|
606
616
|
const solChanges = extractSolBalanceChanges(tx);
|
|
@@ -608,9 +618,8 @@ function transactionToLegs(tx, walletAddress) {
|
|
|
608
618
|
let totalSolCredits = 0n;
|
|
609
619
|
for (const change of solChanges) {
|
|
610
620
|
if (change.change === 0n) continue;
|
|
611
|
-
const isWallet = walletAddress ? change.address.toLowerCase() === walletAddress.toLowerCase() : false;
|
|
612
621
|
const accountId = buildAccountId({
|
|
613
|
-
type:
|
|
622
|
+
type: "external",
|
|
614
623
|
address: change.address
|
|
615
624
|
});
|
|
616
625
|
const solInfo = TOKEN_INFO[KNOWN_TOKENS.SOL];
|
|
@@ -630,7 +639,7 @@ function transactionToLegs(tx, walletAddress) {
|
|
|
630
639
|
amountRaw: change.change.toString().replace("-", ""),
|
|
631
640
|
amountUi: Math.abs(change.changeUi)
|
|
632
641
|
},
|
|
633
|
-
role: determineSolRole(change,
|
|
642
|
+
role: determineSolRole(change, tx, feePayer)
|
|
634
643
|
});
|
|
635
644
|
}
|
|
636
645
|
const networkFee = totalSolDebits - totalSolCredits;
|
|
@@ -652,26 +661,22 @@ function transactionToLegs(tx, walletAddress) {
|
|
|
652
661
|
const tokenChanges = extractTokenBalanceChanges(tx);
|
|
653
662
|
for (const change of tokenChanges) {
|
|
654
663
|
if (change.change.raw === "0") continue;
|
|
655
|
-
const isWallet = walletAddress ? change.owner?.toLowerCase() === walletAddress.toLowerCase() : false;
|
|
656
|
-
const isFeePayer = !walletAddress && feePayer ? change.owner?.toLowerCase() === feePayer : false;
|
|
657
664
|
let accountId;
|
|
658
|
-
if (
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
token: change.tokenInfo.symbol
|
|
674
|
-
});
|
|
665
|
+
if (isDexProtocol(tx.protocol)) {
|
|
666
|
+
const isFeePayer = feePayer && change.owner?.toLowerCase() === feePayer;
|
|
667
|
+
if (isFeePayer) {
|
|
668
|
+
accountId = buildAccountId({
|
|
669
|
+
type: "external",
|
|
670
|
+
address: change.owner || feePayer
|
|
671
|
+
});
|
|
672
|
+
} else {
|
|
673
|
+
accountId = buildAccountId({
|
|
674
|
+
type: "protocol",
|
|
675
|
+
address: change.owner || change.tokenInfo.mint,
|
|
676
|
+
protocol: tx.protocol.id,
|
|
677
|
+
token: change.tokenInfo.symbol
|
|
678
|
+
});
|
|
679
|
+
}
|
|
675
680
|
} else {
|
|
676
681
|
accountId = buildAccountId({
|
|
677
682
|
type: "external",
|
|
@@ -686,41 +691,30 @@ function transactionToLegs(tx, walletAddress) {
|
|
|
686
691
|
amountRaw: change.change.raw.replace("-", ""),
|
|
687
692
|
amountUi: Math.abs(change.change.ui)
|
|
688
693
|
},
|
|
689
|
-
role: determineTokenRole(change,
|
|
694
|
+
role: determineTokenRole(change, tx, feePayer)
|
|
690
695
|
});
|
|
691
696
|
}
|
|
692
697
|
return legs;
|
|
693
698
|
}
|
|
694
|
-
function determineSolRole(change,
|
|
695
|
-
const
|
|
696
|
-
const isFeePayer = !walletAddress && feePayer ? change.address.toLowerCase() === feePayer : false;
|
|
699
|
+
function determineSolRole(change, tx, feePayer) {
|
|
700
|
+
const isFeePayer = feePayer ? change.address.toLowerCase() === feePayer : false;
|
|
697
701
|
const isPositive = change.change > 0n;
|
|
698
702
|
const amountSol = Math.abs(change.changeUi);
|
|
699
|
-
if (isWallet) {
|
|
700
|
-
if (!isPositive && amountSol < 0.01) {
|
|
701
|
-
return "fee";
|
|
702
|
-
}
|
|
703
|
-
if (isPositive) {
|
|
704
|
-
if (tx.protocol?.id === "stake") {
|
|
705
|
-
return "reward";
|
|
706
|
-
}
|
|
707
|
-
return "received";
|
|
708
|
-
}
|
|
709
|
-
return "sent";
|
|
710
|
-
}
|
|
711
703
|
if (isFeePayer && !isPositive && amountSol < 0.01) {
|
|
712
704
|
return "fee";
|
|
713
705
|
}
|
|
714
706
|
if (isPositive) {
|
|
707
|
+
if (tx.protocol?.id === "stake") {
|
|
708
|
+
return "reward";
|
|
709
|
+
}
|
|
715
710
|
return "received";
|
|
716
711
|
}
|
|
717
712
|
return "sent";
|
|
718
713
|
}
|
|
719
|
-
function determineTokenRole(change,
|
|
720
|
-
const
|
|
721
|
-
const isFeePayer = !walletAddress && feePayer ? change.owner?.toLowerCase() === feePayer : false;
|
|
714
|
+
function determineTokenRole(change, tx, feePayer) {
|
|
715
|
+
const isFeePayer = feePayer ? change.owner?.toLowerCase() === feePayer : false;
|
|
722
716
|
const isPositive = change.change.ui > 0;
|
|
723
|
-
if (
|
|
717
|
+
if (isFeePayer) {
|
|
724
718
|
return isPositive ? "received" : "sent";
|
|
725
719
|
}
|
|
726
720
|
if (isDexProtocol(tx.protocol)) {
|
|
@@ -734,85 +728,35 @@ var TransferClassifier = class {
|
|
|
734
728
|
name = "transfer";
|
|
735
729
|
priority = 20;
|
|
736
730
|
classify(context) {
|
|
737
|
-
const { legs,
|
|
731
|
+
const { legs, tx } = context;
|
|
738
732
|
const facilitator = tx.accountKeys ? detectFacilitator(tx.accountKeys) : null;
|
|
739
|
-
const
|
|
740
|
-
|
|
741
|
-
let participantPrefix;
|
|
742
|
-
if (walletAddress) {
|
|
743
|
-
participantAddress = walletAddress.toLowerCase();
|
|
744
|
-
participantPrefix = `wallet:${participantAddress}`;
|
|
745
|
-
} else {
|
|
746
|
-
const feeLeg = legs.find(
|
|
747
|
-
(leg) => leg.role === "fee" && leg.accountId.startsWith("external:")
|
|
748
|
-
);
|
|
749
|
-
if (!feeLeg) return null;
|
|
750
|
-
participantAddress = feeLeg.accountId.replace("external:", "").toLowerCase();
|
|
751
|
-
participantPrefix = `external:${participantAddress}`;
|
|
752
|
-
}
|
|
753
|
-
const participantSent = legs.filter(
|
|
754
|
-
(l) => l.accountId.toLowerCase().startsWith(participantPrefix.toLowerCase()) && l.side === "debit" && l.role === "sent"
|
|
733
|
+
const senderLeg = legs.find(
|
|
734
|
+
(l) => l.accountId.startsWith("external:") && l.side === "debit" && l.role === "sent"
|
|
755
735
|
);
|
|
756
|
-
|
|
757
|
-
|
|
736
|
+
if (!senderLeg) return null;
|
|
737
|
+
const sender = senderLeg.accountId.replace("external:", "");
|
|
738
|
+
const receiverLeg = legs.find(
|
|
739
|
+
(l) => l.accountId.startsWith("external:") && l.side === "credit" && l.role === "received" && l.amount.token.mint === senderLeg.amount.token.mint
|
|
758
740
|
);
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
counterparty: {
|
|
777
|
-
type: "unknown",
|
|
778
|
-
address: receiverAddress,
|
|
779
|
-
name: `${receiverAddress.slice(0, 8)}...`
|
|
780
|
-
},
|
|
781
|
-
confidence: isObserverMode ? 0.9 : 0.95,
|
|
782
|
-
isRelevant: true,
|
|
783
|
-
metadata: {
|
|
784
|
-
...isObserverMode && { observer_mode: true, sender: participantAddress },
|
|
785
|
-
...facilitator && { facilitator, payment_type: "facilitated" }
|
|
786
|
-
}
|
|
787
|
-
};
|
|
788
|
-
}
|
|
789
|
-
}
|
|
790
|
-
for (const received of participantReceived) {
|
|
791
|
-
const matchingSent = otherSent.find(
|
|
792
|
-
(s) => s.amount.token.mint === received.amount.token.mint
|
|
793
|
-
);
|
|
794
|
-
if (matchingSent) {
|
|
795
|
-
const senderAddress = matchingSent.accountId.replace("external:", "");
|
|
796
|
-
return {
|
|
797
|
-
primaryType: "transfer",
|
|
798
|
-
direction: isObserverMode ? "neutral" : "incoming",
|
|
799
|
-
primaryAmount: received.amount,
|
|
800
|
-
secondaryAmount: null,
|
|
801
|
-
counterparty: {
|
|
802
|
-
type: "unknown",
|
|
803
|
-
address: senderAddress,
|
|
804
|
-
name: `${senderAddress.slice(0, 8)}...`
|
|
805
|
-
},
|
|
806
|
-
confidence: isObserverMode ? 0.9 : 0.95,
|
|
807
|
-
isRelevant: true,
|
|
808
|
-
metadata: {
|
|
809
|
-
...isObserverMode && { observer_mode: true, receiver: participantAddress },
|
|
810
|
-
...facilitator && { facilitator, payment_type: "facilitated" }
|
|
811
|
-
}
|
|
812
|
-
};
|
|
741
|
+
if (!receiverLeg) return null;
|
|
742
|
+
const receiver = receiverLeg.accountId.replace("external:", "");
|
|
743
|
+
return {
|
|
744
|
+
primaryType: "transfer",
|
|
745
|
+
primaryAmount: senderLeg.amount,
|
|
746
|
+
secondaryAmount: null,
|
|
747
|
+
sender,
|
|
748
|
+
receiver,
|
|
749
|
+
counterparty: {
|
|
750
|
+
type: "wallet",
|
|
751
|
+
address: receiver,
|
|
752
|
+
name: `${receiver.slice(0, 8)}...`
|
|
753
|
+
},
|
|
754
|
+
confidence: 0.95,
|
|
755
|
+
isRelevant: true,
|
|
756
|
+
metadata: {
|
|
757
|
+
...facilitator && { facilitator, payment_type: "facilitated" }
|
|
813
758
|
}
|
|
814
|
-
}
|
|
815
|
-
return null;
|
|
759
|
+
};
|
|
816
760
|
}
|
|
817
761
|
};
|
|
818
762
|
|
|
@@ -857,9 +801,54 @@ var KNOWN_PROGRAMS = {
|
|
|
857
801
|
[STAKE_PROGRAM_ID]: {
|
|
858
802
|
id: "stake",
|
|
859
803
|
name: "Stake Program"
|
|
804
|
+
},
|
|
805
|
+
[STAKE_POOL_PROGRAM_ID]: {
|
|
806
|
+
id: "stake-pool",
|
|
807
|
+
name: "Stake Pool Program"
|
|
808
|
+
},
|
|
809
|
+
[CANDY_GUARD_PROGRAM_ID]: {
|
|
810
|
+
id: "candy-guard",
|
|
811
|
+
name: "Metaplex Candy Guard Program"
|
|
812
|
+
},
|
|
813
|
+
[CANDY_MACHINE_V3_PROGRAM_ID]: {
|
|
814
|
+
id: "candy-machine-v3",
|
|
815
|
+
name: "Metaplex Candy Machine Core Program"
|
|
816
|
+
},
|
|
817
|
+
[BUBBLEGUM_PROGRAM_ID]: {
|
|
818
|
+
id: "bubblegum",
|
|
819
|
+
name: "Bubblegum Program"
|
|
820
|
+
},
|
|
821
|
+
[MAGIC_EDEN_CANDY_MACHINE_ID]: {
|
|
822
|
+
id: "magic-eden-candy-machine",
|
|
823
|
+
name: "Nft Candy Machine Program (Magic Eden)"
|
|
824
|
+
},
|
|
825
|
+
[WORMHOLE_PROGRAM_ID]: {
|
|
826
|
+
id: "wormhole",
|
|
827
|
+
name: "Wormhole"
|
|
828
|
+
},
|
|
829
|
+
[WORMHOLE_TOKEN_BRIDGE_ID]: {
|
|
830
|
+
id: "wormhole-token-bridge",
|
|
831
|
+
name: "Wormhole Token Bridge"
|
|
832
|
+
},
|
|
833
|
+
[DEGODS_BRIDGE_PROGRAM_ID]: {
|
|
834
|
+
id: "degods-bridge",
|
|
835
|
+
name: "DeGods Bridge"
|
|
836
|
+
},
|
|
837
|
+
[DEBRIDGE_PROGRAM_ID]: {
|
|
838
|
+
id: "debridge",
|
|
839
|
+
name: "deBridge"
|
|
840
|
+
},
|
|
841
|
+
[ALLBRIDGE_PROGRAM_ID]: {
|
|
842
|
+
id: "allbridge",
|
|
843
|
+
name: "Allbridge"
|
|
860
844
|
}
|
|
861
845
|
};
|
|
862
846
|
var PRIORITY_ORDER = [
|
|
847
|
+
"wormhole",
|
|
848
|
+
"wormhole-token-bridge",
|
|
849
|
+
"degods-bridge",
|
|
850
|
+
"debridge",
|
|
851
|
+
"allbridge",
|
|
863
852
|
"jupiter",
|
|
864
853
|
"jupiter-v4",
|
|
865
854
|
"raydium",
|
|
@@ -877,9 +866,33 @@ var DEX_PROTOCOL_IDS2 = /* @__PURE__ */ new Set([
|
|
|
877
866
|
"raydium",
|
|
878
867
|
"orca-whirlpool"
|
|
879
868
|
]);
|
|
869
|
+
var NFT_MINT_PROTOCOL_IDS = /* @__PURE__ */ new Set([
|
|
870
|
+
"metaplex",
|
|
871
|
+
"candy-machine-v3",
|
|
872
|
+
"candy-guard",
|
|
873
|
+
"bubblegum",
|
|
874
|
+
"magic-eden-candy-machine"
|
|
875
|
+
]);
|
|
876
|
+
var STAKE_PROTOCOL_IDS = /* @__PURE__ */ new Set(["stake", "stake-pool"]);
|
|
877
|
+
var BRIDGE_PROTOCOL_IDS = /* @__PURE__ */ new Set([
|
|
878
|
+
"wormhole",
|
|
879
|
+
"wormhole-token-bridge",
|
|
880
|
+
"degods-bridge",
|
|
881
|
+
"debridge",
|
|
882
|
+
"allbridge"
|
|
883
|
+
]);
|
|
880
884
|
function isDexProtocolById(protocolId) {
|
|
881
885
|
return protocolId !== void 0 && DEX_PROTOCOL_IDS2.has(protocolId);
|
|
882
886
|
}
|
|
887
|
+
function isNftMintProtocolById(protocolId) {
|
|
888
|
+
return protocolId !== void 0 && NFT_MINT_PROTOCOL_IDS.has(protocolId);
|
|
889
|
+
}
|
|
890
|
+
function isStakeProtocolById(protocolId) {
|
|
891
|
+
return protocolId !== void 0 && STAKE_PROTOCOL_IDS.has(protocolId);
|
|
892
|
+
}
|
|
893
|
+
function isBridgeProtocolById(protocolId) {
|
|
894
|
+
return protocolId !== void 0 && BRIDGE_PROTOCOL_IDS.has(protocolId);
|
|
895
|
+
}
|
|
883
896
|
function detectProtocol(programIds) {
|
|
884
897
|
const detectedProtocols = [];
|
|
885
898
|
for (const programId of programIds) {
|
|
@@ -904,65 +917,46 @@ var SwapClassifier = class {
|
|
|
904
917
|
name = "swap";
|
|
905
918
|
priority = 80;
|
|
906
919
|
classify(context) {
|
|
907
|
-
const { legs,
|
|
908
|
-
const protocolLegs = legs.filter(
|
|
909
|
-
(leg) => leg.accountId.startsWith("protocol:")
|
|
910
|
-
);
|
|
920
|
+
const { legs, tx } = context;
|
|
911
921
|
const hasDexProtocol = isDexProtocolById(tx.protocol?.id);
|
|
912
|
-
if (
|
|
922
|
+
if (!hasDexProtocol) {
|
|
913
923
|
return null;
|
|
914
924
|
}
|
|
915
|
-
const
|
|
916
|
-
|
|
917
|
-
if (walletAddress) {
|
|
918
|
-
participantPrefix = `wallet:${walletAddress}`;
|
|
919
|
-
} else {
|
|
920
|
-
const feeLeg = legs.find(
|
|
921
|
-
(leg) => leg.role === "fee" && leg.accountId.startsWith("external:")
|
|
922
|
-
);
|
|
923
|
-
if (!feeLeg) return null;
|
|
924
|
-
const feePayerAddress = feeLeg.accountId.replace("external:", "");
|
|
925
|
-
participantPrefix = `external:${feePayerAddress}`;
|
|
926
|
-
}
|
|
927
|
-
const participantDebits = legs.filter(
|
|
928
|
-
(leg) => leg.accountId.startsWith(participantPrefix) && leg.side === "debit"
|
|
925
|
+
const feeLeg = legs.find(
|
|
926
|
+
(leg) => leg.role === "fee" && leg.side === "debit"
|
|
929
927
|
);
|
|
930
|
-
const
|
|
931
|
-
|
|
928
|
+
const initiator = feeLeg?.accountId.replace("external:", "") ?? null;
|
|
929
|
+
const tokensOut = legs.filter(
|
|
930
|
+
(leg) => leg.accountId.startsWith("external:") && leg.side === "debit" && (leg.role === "sent" || leg.role === "protocol_deposit")
|
|
932
931
|
);
|
|
933
|
-
const
|
|
934
|
-
(leg) => leg.role === "
|
|
935
|
-
);
|
|
936
|
-
const tokensIn = participantCredits.filter(
|
|
937
|
-
(leg) => leg.role === "received" || leg.role === "protocol_withdraw"
|
|
932
|
+
const tokensIn = legs.filter(
|
|
933
|
+
(leg) => leg.accountId.startsWith("external:") && leg.side === "credit" && (leg.role === "received" || leg.role === "protocol_withdraw")
|
|
938
934
|
);
|
|
939
935
|
if (tokensOut.length === 0 || tokensIn.length === 0) {
|
|
940
936
|
return null;
|
|
941
937
|
}
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
return {
|
|
947
|
-
primaryType: "swap",
|
|
948
|
-
direction: "neutral",
|
|
949
|
-
primaryAmount: tokenOut.amount,
|
|
950
|
-
secondaryAmount: tokenIn.amount,
|
|
951
|
-
counterparty: null,
|
|
952
|
-
confidence: isObserverMode ? 0.85 : 0.9,
|
|
953
|
-
isRelevant: true,
|
|
954
|
-
metadata: {
|
|
955
|
-
swap_type: "token_to_token",
|
|
956
|
-
from_token: tokenOut.amount.token.symbol,
|
|
957
|
-
to_token: tokenIn.amount.token.symbol,
|
|
958
|
-
from_amount: tokenOut.amount.amountUi,
|
|
959
|
-
to_amount: tokenIn.amount.amountUi,
|
|
960
|
-
...isObserverMode && { observer_mode: true }
|
|
961
|
-
}
|
|
962
|
-
};
|
|
963
|
-
}
|
|
938
|
+
const tokenOut = tokensOut[0];
|
|
939
|
+
const tokenIn = tokensIn[0];
|
|
940
|
+
if (tokenOut.amount.token.symbol === tokenIn.amount.token.symbol) {
|
|
941
|
+
return null;
|
|
964
942
|
}
|
|
965
|
-
return
|
|
943
|
+
return {
|
|
944
|
+
primaryType: "swap",
|
|
945
|
+
primaryAmount: tokenOut.amount,
|
|
946
|
+
secondaryAmount: tokenIn.amount,
|
|
947
|
+
sender: initiator,
|
|
948
|
+
receiver: initiator,
|
|
949
|
+
counterparty: null,
|
|
950
|
+
confidence: 0.9,
|
|
951
|
+
isRelevant: true,
|
|
952
|
+
metadata: {
|
|
953
|
+
swap_type: "token_to_token",
|
|
954
|
+
from_token: tokenOut.amount.token.symbol,
|
|
955
|
+
to_token: tokenIn.amount.token.symbol,
|
|
956
|
+
from_amount: tokenOut.amount.amountUi,
|
|
957
|
+
to_amount: tokenIn.amount.amountUi
|
|
958
|
+
}
|
|
959
|
+
};
|
|
966
960
|
}
|
|
967
961
|
};
|
|
968
962
|
|
|
@@ -971,7 +965,7 @@ var AirdropClassifier = class {
|
|
|
971
965
|
name = "airdrop";
|
|
972
966
|
priority = 70;
|
|
973
967
|
classify(context) {
|
|
974
|
-
const { legs,
|
|
968
|
+
const { legs, tx } = context;
|
|
975
969
|
const facilitator = tx.accountKeys ? detectFacilitator(tx.accountKeys) : null;
|
|
976
970
|
const protocolLegs = legs.filter(
|
|
977
971
|
(leg) => leg.accountId.startsWith("protocol:")
|
|
@@ -979,49 +973,41 @@ var AirdropClassifier = class {
|
|
|
979
973
|
if (protocolLegs.length === 0) {
|
|
980
974
|
return null;
|
|
981
975
|
}
|
|
982
|
-
const
|
|
983
|
-
|
|
984
|
-
const participantCredits = legs.filter(
|
|
985
|
-
(leg) => leg.accountId.startsWith(accountPrefix) && leg.side === "credit"
|
|
986
|
-
);
|
|
987
|
-
const participantDebits = legs.filter(
|
|
988
|
-
(leg) => leg.accountId.startsWith(accountPrefix) && leg.side === "debit"
|
|
989
|
-
);
|
|
990
|
-
const tokenReceived = participantCredits.filter(
|
|
991
|
-
(leg) => leg.role === "received" && leg.amount.token.symbol !== "SOL"
|
|
976
|
+
const tokenReceived = legs.filter(
|
|
977
|
+
(leg) => leg.accountId.startsWith("external:") && leg.side === "credit" && leg.role === "received" && leg.amount.token.symbol !== "SOL"
|
|
992
978
|
);
|
|
993
979
|
if (tokenReceived.length === 0) {
|
|
994
980
|
return null;
|
|
995
981
|
}
|
|
996
|
-
const tokenSent =
|
|
997
|
-
(leg) => leg.role === "sent" && leg.amount.token.symbol !== "SOL"
|
|
982
|
+
const tokenSent = legs.filter(
|
|
983
|
+
(leg) => leg.accountId.startsWith("external:") && leg.side === "debit" && leg.role === "sent" && leg.amount.token.symbol !== "SOL"
|
|
998
984
|
);
|
|
999
985
|
if (tokenSent.length > 0) {
|
|
1000
986
|
return null;
|
|
1001
987
|
}
|
|
1002
988
|
const mainToken = tokenReceived[0];
|
|
1003
|
-
const
|
|
1004
|
-
|
|
989
|
+
const receiver = mainToken.accountId.replace("external:", "");
|
|
990
|
+
const senderLeg = legs.find(
|
|
991
|
+
(leg) => leg.side === "debit" && leg.amount.token.mint === mainToken.amount.token.mint
|
|
1005
992
|
);
|
|
1006
|
-
const sender =
|
|
1007
|
-
const receiverAddress = mainToken.accountId.replace(/^(external:|wallet:)/, "");
|
|
993
|
+
const sender = senderLeg ? senderLeg.accountId.replace(/^(external:|protocol:)/, "") : null;
|
|
1008
994
|
return {
|
|
1009
995
|
primaryType: "airdrop",
|
|
1010
|
-
direction: isObserverMode ? "neutral" : "incoming",
|
|
1011
996
|
primaryAmount: mainToken.amount,
|
|
1012
997
|
secondaryAmount: null,
|
|
998
|
+
sender,
|
|
999
|
+
receiver,
|
|
1013
1000
|
counterparty: sender ? {
|
|
1014
|
-
type: "
|
|
1015
|
-
address: sender
|
|
1001
|
+
type: "protocol",
|
|
1002
|
+
address: sender
|
|
1016
1003
|
} : null,
|
|
1017
|
-
confidence:
|
|
1004
|
+
confidence: 0.85,
|
|
1018
1005
|
isRelevant: true,
|
|
1019
1006
|
metadata: {
|
|
1020
1007
|
airdrop_type: "token",
|
|
1021
1008
|
token: mainToken.amount.token.symbol,
|
|
1022
1009
|
amount: mainToken.amount.amountUi,
|
|
1023
|
-
...
|
|
1024
|
-
...facilitator && { facilitator, payment_type: "facilitated" }
|
|
1010
|
+
...facilitator && { facilitator }
|
|
1025
1011
|
}
|
|
1026
1012
|
};
|
|
1027
1013
|
}
|
|
@@ -1032,30 +1018,34 @@ var FeeOnlyClassifier = class {
|
|
|
1032
1018
|
name = "fee-only";
|
|
1033
1019
|
priority = 60;
|
|
1034
1020
|
classify(context) {
|
|
1035
|
-
const { legs
|
|
1036
|
-
const
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
const
|
|
1040
|
-
if (
|
|
1021
|
+
const { legs } = context;
|
|
1022
|
+
const externalLegs = legs.filter(
|
|
1023
|
+
(leg) => leg.accountId.startsWith("external:")
|
|
1024
|
+
);
|
|
1025
|
+
const nonFeeLegs = externalLegs.filter((leg) => leg.role !== "fee");
|
|
1026
|
+
if (nonFeeLegs.length > 0) {
|
|
1041
1027
|
return null;
|
|
1042
1028
|
}
|
|
1043
1029
|
const feeLegs = legs.filter((leg) => leg.role === "fee");
|
|
1044
1030
|
if (feeLegs.length === 0) {
|
|
1045
1031
|
return null;
|
|
1046
1032
|
}
|
|
1033
|
+
const feePayerLeg = feeLegs.find(
|
|
1034
|
+
(leg) => leg.side === "debit" && leg.amount.token.symbol === "SOL"
|
|
1035
|
+
);
|
|
1036
|
+
const feePayer = feePayerLeg?.accountId.replace("external:", "") ?? null;
|
|
1047
1037
|
const totalFee = feeLegs.find((leg) => leg.amount.token.symbol === "SOL");
|
|
1048
1038
|
return {
|
|
1049
1039
|
primaryType: "fee_only",
|
|
1050
|
-
direction: "outgoing",
|
|
1051
1040
|
primaryAmount: totalFee?.amount ?? null,
|
|
1052
1041
|
secondaryAmount: null,
|
|
1042
|
+
sender: feePayer,
|
|
1043
|
+
receiver: null,
|
|
1053
1044
|
counterparty: null,
|
|
1054
|
-
confidence:
|
|
1045
|
+
confidence: 0.95,
|
|
1055
1046
|
isRelevant: false,
|
|
1056
1047
|
metadata: {
|
|
1057
|
-
fee_type: "network"
|
|
1058
|
-
...isObserverMode && { observer_mode: true }
|
|
1048
|
+
fee_type: "network"
|
|
1059
1049
|
}
|
|
1060
1050
|
};
|
|
1061
1051
|
}
|
|
@@ -1066,59 +1056,31 @@ var SolanaPayClassifier = class {
|
|
|
1066
1056
|
name = "solana-pay";
|
|
1067
1057
|
priority = 95;
|
|
1068
1058
|
classify(context) {
|
|
1069
|
-
const { tx,
|
|
1059
|
+
const { tx, legs } = context;
|
|
1070
1060
|
if (!isSolanaPayTransaction(tx.programIds, tx.memo)) {
|
|
1071
1061
|
return null;
|
|
1072
1062
|
}
|
|
1073
1063
|
const memo = parseSolanaPayMemo(tx.memo);
|
|
1074
|
-
const
|
|
1075
|
-
|
|
1076
|
-
const senderLeg = legs.find(
|
|
1077
|
-
(leg) => leg.accountId.startsWith("external:") && leg.side === "debit" && leg.role === "sent"
|
|
1078
|
-
);
|
|
1079
|
-
const receiverLeg = legs.find(
|
|
1080
|
-
(leg) => leg.accountId.startsWith("external:") && leg.side === "credit" && leg.role === "received"
|
|
1081
|
-
);
|
|
1082
|
-
const primaryAmount2 = senderLeg?.amount ?? receiverLeg?.amount ?? null;
|
|
1083
|
-
const senderAddress = senderLeg?.accountId.replace("external:", "");
|
|
1084
|
-
const receiverAddress = receiverLeg?.accountId.replace("external:", "");
|
|
1085
|
-
return {
|
|
1086
|
-
primaryType: "transfer",
|
|
1087
|
-
direction: "neutral",
|
|
1088
|
-
primaryAmount: primaryAmount2,
|
|
1089
|
-
secondaryAmount: null,
|
|
1090
|
-
counterparty: memo.merchant ? { address: receiverAddress ?? "", name: memo.merchant, type: "merchant" } : null,
|
|
1091
|
-
confidence: 0.95,
|
|
1092
|
-
isRelevant: true,
|
|
1093
|
-
metadata: {
|
|
1094
|
-
payment_type: "solana_pay",
|
|
1095
|
-
observer_mode: true,
|
|
1096
|
-
sender: senderAddress,
|
|
1097
|
-
receiver: receiverAddress,
|
|
1098
|
-
memo: memo.raw,
|
|
1099
|
-
merchant: memo.merchant,
|
|
1100
|
-
item: memo.item,
|
|
1101
|
-
reference: memo.reference,
|
|
1102
|
-
label: memo.label,
|
|
1103
|
-
message: memo.message
|
|
1104
|
-
}
|
|
1105
|
-
};
|
|
1106
|
-
}
|
|
1107
|
-
const walletPrefix = `wallet:${walletAddress}`;
|
|
1108
|
-
const userSent = legs.find(
|
|
1109
|
-
(leg) => leg.accountId.includes(walletPrefix) && leg.side === "debit" && leg.role === "sent"
|
|
1064
|
+
const senderLeg = legs.find(
|
|
1065
|
+
(leg) => leg.accountId.startsWith("external:") && leg.side === "debit" && leg.role === "sent"
|
|
1110
1066
|
);
|
|
1111
|
-
const
|
|
1112
|
-
(leg) => leg.accountId.
|
|
1067
|
+
const receiverLeg = legs.find(
|
|
1068
|
+
(leg) => leg.accountId.startsWith("external:") && leg.side === "credit" && leg.role === "received"
|
|
1113
1069
|
);
|
|
1114
|
-
const
|
|
1115
|
-
const
|
|
1070
|
+
const sender = senderLeg?.accountId.replace("external:", "") ?? null;
|
|
1071
|
+
const receiver = receiverLeg?.accountId.replace("external:", "") ?? null;
|
|
1072
|
+
const primaryAmount = senderLeg?.amount ?? receiverLeg?.amount ?? null;
|
|
1116
1073
|
return {
|
|
1117
1074
|
primaryType: "transfer",
|
|
1118
|
-
direction,
|
|
1119
1075
|
primaryAmount,
|
|
1120
1076
|
secondaryAmount: null,
|
|
1121
|
-
|
|
1077
|
+
sender,
|
|
1078
|
+
receiver,
|
|
1079
|
+
counterparty: receiver ? {
|
|
1080
|
+
address: receiver,
|
|
1081
|
+
name: memo.merchant ?? void 0,
|
|
1082
|
+
type: memo.merchant ? "merchant" : "wallet"
|
|
1083
|
+
} : null,
|
|
1122
1084
|
confidence: 0.98,
|
|
1123
1085
|
isRelevant: true,
|
|
1124
1086
|
metadata: {
|
|
@@ -1134,11 +1096,188 @@ var SolanaPayClassifier = class {
|
|
|
1134
1096
|
}
|
|
1135
1097
|
};
|
|
1136
1098
|
|
|
1099
|
+
// ../classification/src/classifiers/nft-mint-classifier.ts
|
|
1100
|
+
var NftMintClassifier = class {
|
|
1101
|
+
name = "nft-mint";
|
|
1102
|
+
priority = 85;
|
|
1103
|
+
classify(context) {
|
|
1104
|
+
const { legs, tx } = context;
|
|
1105
|
+
const hasNftMintProtocol = isNftMintProtocolById(tx.protocol?.id);
|
|
1106
|
+
if (!hasNftMintProtocol) {
|
|
1107
|
+
return null;
|
|
1108
|
+
}
|
|
1109
|
+
const nftCredits = legs.filter(
|
|
1110
|
+
(leg) => leg.side === "credit" && leg.amount.token.decimals === 0 && leg.amount.amountUi >= 1 && (leg.role === "received" || leg.role === "protocol_withdraw")
|
|
1111
|
+
);
|
|
1112
|
+
if (nftCredits.length === 0) {
|
|
1113
|
+
return null;
|
|
1114
|
+
}
|
|
1115
|
+
const primaryNft = nftCredits[0];
|
|
1116
|
+
const minter = primaryNft.accountId.replace("external:", "");
|
|
1117
|
+
const paymentLeg = legs.find(
|
|
1118
|
+
(leg) => leg.side === "debit" && leg.role === "sent" && leg.amount.token.symbol === "SOL"
|
|
1119
|
+
);
|
|
1120
|
+
const totalMinted = nftCredits.reduce(
|
|
1121
|
+
(sum, leg) => sum + leg.amount.amountUi,
|
|
1122
|
+
0
|
|
1123
|
+
);
|
|
1124
|
+
return {
|
|
1125
|
+
primaryType: "nft_mint",
|
|
1126
|
+
primaryAmount: primaryNft.amount,
|
|
1127
|
+
secondaryAmount: paymentLeg?.amount ?? null,
|
|
1128
|
+
sender: null,
|
|
1129
|
+
receiver: minter,
|
|
1130
|
+
counterparty: null,
|
|
1131
|
+
confidence: 0.9,
|
|
1132
|
+
isRelevant: true,
|
|
1133
|
+
metadata: {
|
|
1134
|
+
nft_mint: primaryNft.amount.token.mint,
|
|
1135
|
+
nft_name: primaryNft.amount.token.name,
|
|
1136
|
+
quantity: totalMinted,
|
|
1137
|
+
mint_price: paymentLeg?.amount.amountUi,
|
|
1138
|
+
protocol: tx.protocol?.id
|
|
1139
|
+
}
|
|
1140
|
+
};
|
|
1141
|
+
}
|
|
1142
|
+
};
|
|
1143
|
+
|
|
1144
|
+
// ../classification/src/classifiers/stake-deposit-classifier.ts
|
|
1145
|
+
var StakeDepositClassifier = class {
|
|
1146
|
+
name = "stake-deposit";
|
|
1147
|
+
priority = 82;
|
|
1148
|
+
classify(context) {
|
|
1149
|
+
const { legs, tx } = context;
|
|
1150
|
+
const hasStakeProtocol = isStakeProtocolById(tx.protocol?.id);
|
|
1151
|
+
if (!hasStakeProtocol) {
|
|
1152
|
+
return null;
|
|
1153
|
+
}
|
|
1154
|
+
const solDebit = legs.find(
|
|
1155
|
+
(leg) => leg.accountId.startsWith("external:") && leg.side === "debit" && leg.amount.token.symbol === "SOL" && (leg.role === "sent" || leg.role === "protocol_deposit")
|
|
1156
|
+
);
|
|
1157
|
+
if (!solDebit) {
|
|
1158
|
+
return null;
|
|
1159
|
+
}
|
|
1160
|
+
const staker = solDebit.accountId.replace("external:", "");
|
|
1161
|
+
return {
|
|
1162
|
+
primaryType: "stake_deposit",
|
|
1163
|
+
primaryAmount: solDebit.amount,
|
|
1164
|
+
secondaryAmount: null,
|
|
1165
|
+
sender: staker,
|
|
1166
|
+
receiver: null,
|
|
1167
|
+
counterparty: null,
|
|
1168
|
+
confidence: 0.9,
|
|
1169
|
+
isRelevant: true,
|
|
1170
|
+
metadata: {
|
|
1171
|
+
stake_amount: solDebit.amount.amountUi,
|
|
1172
|
+
protocol: tx.protocol?.id
|
|
1173
|
+
}
|
|
1174
|
+
};
|
|
1175
|
+
}
|
|
1176
|
+
};
|
|
1177
|
+
|
|
1178
|
+
// ../classification/src/classifiers/stake-withdraw-classifier.ts
|
|
1179
|
+
var StakeWithdrawClassifier = class {
|
|
1180
|
+
name = "stake-withdraw";
|
|
1181
|
+
priority = 81;
|
|
1182
|
+
classify(context) {
|
|
1183
|
+
const { legs, tx } = context;
|
|
1184
|
+
const hasStakeProtocol = isStakeProtocolById(tx.protocol?.id);
|
|
1185
|
+
if (!hasStakeProtocol) {
|
|
1186
|
+
return null;
|
|
1187
|
+
}
|
|
1188
|
+
const solCredit = legs.find(
|
|
1189
|
+
(leg) => leg.accountId.startsWith("external:") && leg.side === "credit" && leg.amount.token.symbol === "SOL" && (leg.role === "received" || leg.role === "protocol_withdraw")
|
|
1190
|
+
);
|
|
1191
|
+
if (!solCredit) {
|
|
1192
|
+
return null;
|
|
1193
|
+
}
|
|
1194
|
+
const solDebit = legs.find(
|
|
1195
|
+
(leg) => leg.accountId.startsWith("external:") && leg.side === "debit" && leg.amount.token.symbol === "SOL" && (leg.role === "sent" || leg.role === "protocol_deposit")
|
|
1196
|
+
);
|
|
1197
|
+
if (solDebit) {
|
|
1198
|
+
return null;
|
|
1199
|
+
}
|
|
1200
|
+
const withdrawer = solCredit.accountId.replace("external:", "");
|
|
1201
|
+
return {
|
|
1202
|
+
primaryType: "stake_withdraw",
|
|
1203
|
+
primaryAmount: solCredit.amount,
|
|
1204
|
+
secondaryAmount: null,
|
|
1205
|
+
sender: null,
|
|
1206
|
+
receiver: withdrawer,
|
|
1207
|
+
counterparty: null,
|
|
1208
|
+
confidence: 0.9,
|
|
1209
|
+
isRelevant: true,
|
|
1210
|
+
metadata: {
|
|
1211
|
+
withdraw_amount: solCredit.amount.amountUi,
|
|
1212
|
+
protocol: tx.protocol?.id
|
|
1213
|
+
}
|
|
1214
|
+
};
|
|
1215
|
+
}
|
|
1216
|
+
};
|
|
1217
|
+
|
|
1218
|
+
// ../classification/src/classifiers/bridge-classifier.ts
|
|
1219
|
+
var BridgeClassifier = class {
|
|
1220
|
+
name = "bridge";
|
|
1221
|
+
priority = 88;
|
|
1222
|
+
classify(context) {
|
|
1223
|
+
const { legs, tx } = context;
|
|
1224
|
+
const hasBridgeProtocol = isBridgeProtocolById(tx.protocol?.id);
|
|
1225
|
+
if (!hasBridgeProtocol) {
|
|
1226
|
+
return null;
|
|
1227
|
+
}
|
|
1228
|
+
const tokensOut = legs.filter(
|
|
1229
|
+
(leg) => leg.accountId.startsWith("external:") && leg.side === "debit" && leg.role !== "fee" && (leg.role === "sent" || leg.role === "protocol_deposit")
|
|
1230
|
+
);
|
|
1231
|
+
const tokensIn = legs.filter(
|
|
1232
|
+
(leg) => leg.accountId.startsWith("external:") && leg.side === "credit" && (leg.role === "received" || leg.role === "protocol_withdraw")
|
|
1233
|
+
);
|
|
1234
|
+
let primaryType;
|
|
1235
|
+
let primaryAmount = null;
|
|
1236
|
+
let participant = null;
|
|
1237
|
+
if (tokensIn.length > 0 && tokensOut.length === 0) {
|
|
1238
|
+
primaryType = "bridge_in";
|
|
1239
|
+
const creditLeg = tokensIn[0];
|
|
1240
|
+
primaryAmount = creditLeg.amount;
|
|
1241
|
+
participant = creditLeg.accountId.replace("external:", "");
|
|
1242
|
+
} else if (tokensOut.length > 0 && tokensIn.length === 0) {
|
|
1243
|
+
primaryType = "bridge_out";
|
|
1244
|
+
const debitLeg = tokensOut[0];
|
|
1245
|
+
primaryAmount = debitLeg.amount;
|
|
1246
|
+
participant = debitLeg.accountId.replace("external:", "");
|
|
1247
|
+
} else if (tokensIn.length > 0 && tokensOut.length > 0) {
|
|
1248
|
+
primaryType = "bridge_in";
|
|
1249
|
+
const creditLeg = tokensIn[0];
|
|
1250
|
+
primaryAmount = creditLeg.amount;
|
|
1251
|
+
participant = creditLeg.accountId.replace("external:", "");
|
|
1252
|
+
} else {
|
|
1253
|
+
return null;
|
|
1254
|
+
}
|
|
1255
|
+
return {
|
|
1256
|
+
primaryType,
|
|
1257
|
+
primaryAmount,
|
|
1258
|
+
secondaryAmount: null,
|
|
1259
|
+
sender: primaryType === "bridge_out" ? participant : null,
|
|
1260
|
+
receiver: primaryType === "bridge_in" ? participant : null,
|
|
1261
|
+
counterparty: null,
|
|
1262
|
+
confidence: 0.9,
|
|
1263
|
+
isRelevant: true,
|
|
1264
|
+
metadata: {
|
|
1265
|
+
bridge_protocol: tx.protocol?.id,
|
|
1266
|
+
bridge_name: tx.protocol?.name
|
|
1267
|
+
}
|
|
1268
|
+
};
|
|
1269
|
+
}
|
|
1270
|
+
};
|
|
1271
|
+
|
|
1137
1272
|
// ../classification/src/engine/classification-service.ts
|
|
1138
1273
|
var ClassificationService = class {
|
|
1139
1274
|
classifiers = [];
|
|
1140
1275
|
constructor() {
|
|
1141
1276
|
this.registerClassifier(new SolanaPayClassifier());
|
|
1277
|
+
this.registerClassifier(new BridgeClassifier());
|
|
1278
|
+
this.registerClassifier(new NftMintClassifier());
|
|
1279
|
+
this.registerClassifier(new StakeDepositClassifier());
|
|
1280
|
+
this.registerClassifier(new StakeWithdrawClassifier());
|
|
1142
1281
|
this.registerClassifier(new SwapClassifier());
|
|
1143
1282
|
this.registerClassifier(new AirdropClassifier());
|
|
1144
1283
|
this.registerClassifier(new TransferClassifier());
|
|
@@ -1148,8 +1287,8 @@ var ClassificationService = class {
|
|
|
1148
1287
|
this.classifiers.push(classifier);
|
|
1149
1288
|
this.classifiers.sort((a, b) => b.priority - a.priority);
|
|
1150
1289
|
}
|
|
1151
|
-
classify(legs,
|
|
1152
|
-
const context = { legs,
|
|
1290
|
+
classify(legs, tx) {
|
|
1291
|
+
const context = { legs, tx };
|
|
1153
1292
|
for (const classifier of this.classifiers) {
|
|
1154
1293
|
const result = classifier.classify(context);
|
|
1155
1294
|
if (result && result.isRelevant) {
|
|
@@ -1158,9 +1297,10 @@ var ClassificationService = class {
|
|
|
1158
1297
|
}
|
|
1159
1298
|
return {
|
|
1160
1299
|
primaryType: "other",
|
|
1161
|
-
direction: "neutral",
|
|
1162
1300
|
primaryAmount: null,
|
|
1163
1301
|
secondaryAmount: null,
|
|
1302
|
+
sender: null,
|
|
1303
|
+
receiver: null,
|
|
1164
1304
|
counterparty: null,
|
|
1165
1305
|
confidence: 0,
|
|
1166
1306
|
isRelevant: false,
|
|
@@ -1169,8 +1309,8 @@ var ClassificationService = class {
|
|
|
1169
1309
|
}
|
|
1170
1310
|
};
|
|
1171
1311
|
var classificationService = new ClassificationService();
|
|
1172
|
-
function classifyTransaction(legs,
|
|
1173
|
-
return classificationService.classify(legs,
|
|
1312
|
+
function classifyTransaction(legs, tx) {
|
|
1313
|
+
return classificationService.classify(legs, tx);
|
|
1174
1314
|
}
|
|
1175
1315
|
|
|
1176
1316
|
// ../domain/src/tx/spam-filter.ts
|
|
@@ -1244,8 +1384,8 @@ function createIndexer(options) {
|
|
|
1244
1384
|
);
|
|
1245
1385
|
const classified = transactions.map((tx) => {
|
|
1246
1386
|
tx.protocol = detectProtocol(tx.programIds);
|
|
1247
|
-
const legs = transactionToLegs(tx
|
|
1248
|
-
const classification = classifyTransaction(legs,
|
|
1387
|
+
const legs = transactionToLegs(tx);
|
|
1388
|
+
const classification = classifyTransaction(legs, tx);
|
|
1249
1389
|
return { tx, classification, legs };
|
|
1250
1390
|
});
|
|
1251
1391
|
return classified;
|
|
@@ -1274,8 +1414,8 @@ function createIndexer(options) {
|
|
|
1274
1414
|
);
|
|
1275
1415
|
const classified = transactions.map((tx) => {
|
|
1276
1416
|
tx.protocol = detectProtocol(tx.programIds);
|
|
1277
|
-
const legs = transactionToLegs(tx
|
|
1278
|
-
const classification = classifyTransaction(legs,
|
|
1417
|
+
const legs = transactionToLegs(tx);
|
|
1418
|
+
const classification = classifyTransaction(legs, tx);
|
|
1279
1419
|
return { tx, classification, legs };
|
|
1280
1420
|
});
|
|
1281
1421
|
const nonSpam = filterSpamTransactions(classified, spamConfig);
|
|
@@ -1289,14 +1429,14 @@ function createIndexer(options) {
|
|
|
1289
1429
|
}
|
|
1290
1430
|
return accumulated.slice(0, limit);
|
|
1291
1431
|
},
|
|
1292
|
-
async getTransaction(signature2
|
|
1432
|
+
async getTransaction(signature2) {
|
|
1293
1433
|
const tx = await fetchTransaction(client.rpc, signature2);
|
|
1294
1434
|
if (!tx) {
|
|
1295
1435
|
return null;
|
|
1296
1436
|
}
|
|
1297
1437
|
tx.protocol = detectProtocol(tx.programIds);
|
|
1298
|
-
const legs = transactionToLegs(tx
|
|
1299
|
-
const classification = classifyTransaction(legs,
|
|
1438
|
+
const legs = transactionToLegs(tx);
|
|
1439
|
+
const classification = classifyTransaction(legs, tx);
|
|
1300
1440
|
return { tx, classification, legs };
|
|
1301
1441
|
},
|
|
1302
1442
|
async getRawTransaction(signature2) {
|