@@ -3,9 +3,11 @@ import { SuiClient as Client, getFullnodeUrl } from "@mysten/sui/client";
33import type { Signer } from "@mysten/sui/cryptography" ;
44import { Ed25519Keypair } from "@mysten/sui/keypairs/ed25519" ;
55import { Transaction as SuiTransaction } from "@mysten/sui/transactions" ;
6- import type { MintBatchArg , NbtcPkgCfg , SuiTxDigest } from "./models" ;
6+ import { btcNetworkCfg , type MintBatchArg , type NbtcPkgCfg , type SuiTxDigest } from "./models" ;
77import { logError , logger } from "@gonative-cc/lib/logger" ;
88import { nBTCContractModule } from "@gonative-cc/nbtc" ;
9+ import { Transaction , payments , script } from "bitcoinjs-lib" ;
10+ import type { D1Database } from "@cloudflare/workers-types" ;
911
1012const LC_MODULE = "light_client" ;
1113
@@ -18,20 +20,22 @@ export interface SuiClientI {
1820
1921export type SuiClientConstructor = ( config : NbtcPkgCfg ) => SuiClientI ;
2022
21- export function NewSuiClient ( mnemonic : string ) : SuiClientConstructor {
22- return ( config : NbtcPkgCfg ) => new SuiClient ( config , mnemonic ) ;
23+ export function NewSuiClient ( mnemonic : string , db : D1Database ) : SuiClientConstructor {
24+ return ( config : NbtcPkgCfg ) => new SuiClient ( config , mnemonic , db ) ;
2325}
2426
2527export class SuiClient implements SuiClientI {
2628 private client : Client ;
2729 private signer : Signer ;
2830 private config : NbtcPkgCfg ;
31+ private db : D1Database ;
2932
30- constructor ( config : NbtcPkgCfg , mnemonic : string ) {
33+ constructor ( config : NbtcPkgCfg , mnemonic : string , db ?: D1Database ) {
3134 this . config = config ;
3235 this . client = new Client ( { url : getFullnodeUrl ( config . sui_network ) } ) ;
3336 // TODO: instead of mnemonic, let's use the Signer interface in the config
3437 this . signer = Ed25519Keypair . deriveKeypair ( mnemonic ) ;
38+ this . db = db ! ;
3539 logger . debug ( {
3640 msg : "Sui Client Initialized" ,
3741 suiSignerAddress : this . signer . getPublicKey ( ) . toSuiAddress ( ) ,
@@ -129,6 +133,17 @@ export class SuiClient implements SuiClientI {
129133 const proofLittleEndian = args . proof . proofPath . map ( ( p ) => Array . from ( p ) ) ;
130134 const txBytes = Array . from ( args . tx . toBuffer ( ) ) ;
131135
136+ // Extract sender address and check sanctions
137+ const senderAddress = await this . extractSenderAddress ( args . tx ) ;
138+ if ( senderAddress && ( await this . isSanctioned ( senderAddress ) ) ) {
139+ logger . error ( {
140+ msg : "Sanctioned address detected, skipping mint" ,
141+ txId : args . tx . getId ( ) ,
142+ senderAddress,
143+ } ) ;
144+ continue ;
145+ }
146+
132147 tx . add (
133148 nBTCContractModule . mint ( {
134149 package : this . config . nbtc_pkg ,
@@ -168,6 +183,58 @@ export class SuiClient implements SuiClientI {
168183 return [ success , result . digest ] ;
169184 }
170185
186+ private async extractSenderAddress ( tx : Transaction ) : Promise < string | null > {
187+ try {
188+ if ( tx . ins . length === 0 ) return null ;
189+
190+ const firstInput = tx . ins [ 0 ] ;
191+ const network = btcNetworkCfg [ this . config . btc_network ] ;
192+
193+ if ( firstInput && firstInput . witness && firstInput . witness . length >= 2 ) {
194+ const pubKey = firstInput . witness [ 1 ] ;
195+ const { address } = payments . p2wpkh ( {
196+ pubkey : pubKey ,
197+ network : network ,
198+ } ) ;
199+ return address || null ;
200+ }
201+
202+ const scriptSig = firstInput ?. script ;
203+ if ( scriptSig && scriptSig . length >= 65 ) {
204+ const chunks = script . decompile ( scriptSig ) ;
205+ if ( ! chunks ) return null ;
206+
207+ const pubKey = chunks [ chunks . length - 1 ] as Buffer ;
208+
209+ const { address } = payments . p2pkh ( {
210+ pubkey : pubKey ,
211+ network : network ,
212+ } ) ;
213+ return address || null ;
214+ }
215+
216+ return null ;
217+ } catch ( e ) {
218+ console . error ( "Failed to extract sender address" , e ) ;
219+ return null ;
220+ }
221+ }
222+
223+ private async isSanctioned ( btcAddress : string ) : Promise < boolean > {
224+ try {
225+ const result = await this . db
226+ . prepare (
227+ "SELECT 1 FROM SanctionedCryptoAddresses WHERE wallet_address = ? AND address_type = 'BTC'" ,
228+ )
229+ . bind ( btcAddress )
230+ . first ( ) ;
231+ return result !== null ;
232+ } catch ( e ) {
233+ logError ( { method : "isSanctioned" , msg : "Failed to check sanctions" , btcAddress } , e ) ;
234+ return false ;
235+ }
236+ }
237+
171238 /**
172239 * Wrapper for mintNbtcBatch that catches pre-submission errors.
173240 * Returns:
0 commit comments