@@ -20,6 +20,85 @@ export enum ProgramID {
2020 Token2022ProgramId = 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb' ,
2121}
2222
23+ /**
24+ * Token-2022 (SPL Token Extensions) that BitGo has explicit custody handling for.
25+ * This set is the onboarding safety gate: a mint whose
26+ * TLV data declares any extension NOT represented here must be rejected at onboarding
27+ * and escalated to engineering — no soft pass.
28+ */
29+ export enum SolTokenExtensionType {
30+ TransferFee = 'transferFee' ,
31+ TransferHook = 'transferHook' ,
32+ PermanentDelegate = 'permanentDelegate' ,
33+ InterestBearing = 'interestBearing' ,
34+ ScaledUiAmount = 'scaledUiAmount' ,
35+ DefaultAccountState = 'defaultAccountState' ,
36+ }
37+
38+ /** On-chain authority addresses relevant to Token-2022 extensions, captured at onboarding. */
39+ export interface SolTokenAuthorities {
40+ freezeAuthority ?: string ;
41+ mintAuthority ?: string ;
42+ transferFeeConfigAuthority ?: string ;
43+ withdrawWithheldAuthority ?: string ;
44+ permanentDelegate ?: string ;
45+ rateAuthority ?: string ;
46+ }
47+
48+ export interface SolTransferFeeConfig {
49+ transferFeeBasisPoints : number ;
50+ /** Raw base units, stringified to avoid precision loss. */
51+ maximumFee : string ;
52+ }
53+
54+ export interface SolDefaultAccountStateConfig {
55+ /** True when the mint's Default Account State is Frozen. */
56+ frozen : boolean ;
57+ /** True when a permissionless thaw program (Token ACL etc.) is associated */
58+ permissionlessThaw : boolean ;
59+ }
60+
61+ export interface SolInterestBearingConfig {
62+ /** Annual interest rate in basis points. */
63+ rateBasisPoints : number ;
64+ /** 'continuous' (issuer mints frequently) or 'redeemOnMaturity' (accrued not transferable until settlement). */
65+ settlementModel ?: 'continuous' | 'redeemOnMaturity' ;
66+ }
67+ export interface SolScaledUiAmountConfig {
68+ /** UiAmountMultiplier active at onboarding; time-series history is tracked off-chain from day one. */
69+ initialMultiplier : string ;
70+ }
71+ /**
72+ * Per-mint Token-2022 extension configuration detected at onboarding.
73+ * Absent => classic SPL / no modeled extensions.
74+ */
75+ export interface SolTokenExtensions {
76+ /** Every extension detected on the mint's TLV data. Onboarding hard-stops if any is not a SolTokenExtensionType. */
77+ detected : SolTokenExtensionType [ ] ;
78+ authorities ?: SolTokenAuthorities ;
79+ /** Resolved human-readable issuer name for notifications and transaction history. */
80+ issuerName ?: string ;
81+ transferFee ?: SolTransferFeeConfig ;
82+ /** Transfer Hook program id. The extra-account-meta list is resolved fresh at tx time — never stored. */
83+ transferHookProgramId ?: string ;
84+ interestBearing ?: SolInterestBearingConfig ;
85+ scaledUiAmount ?: SolScaledUiAmountConfig ;
86+ defaultAccountState ?: SolDefaultAccountStateConfig ;
87+ }
88+
89+ /** Extensions BitGo can safely custody (the onboarding allowlist). */
90+ export const SUPPORTED_SOL_TOKEN_EXTENSIONS : ReadonlySet < SolTokenExtensionType > = new Set (
91+ Object . values ( SolTokenExtensionType )
92+ ) ;
93+
94+ /**
95+ * Returns the detected extensions BitGo has no handling code for.
96+ * A non-empty result MUST hard-stop onboarding.
97+ */
98+ export function getUnsupportedSolTokenExtensions ( detected : readonly string [ ] ) : string [ ] {
99+ return detected . filter ( ( ext ) => ! SUPPORTED_SOL_TOKEN_EXTENSIONS . has ( ext as SolTokenExtensionType ) ) ;
100+ }
101+
23102export interface AccountConstructorOptions {
24103 id : string ;
25104 fullName : string ;
@@ -128,6 +207,7 @@ export interface SolCoinConstructorOptions extends AccountConstructorOptions {
128207 tokenAddress : string ;
129208 contractAddress : string ;
130209 programId : string ;
210+ tokenExtensions ?: SolTokenExtensions ;
131211}
132212
133213export interface XrpCoinConstructorOptions extends AccountConstructorOptions {
@@ -453,6 +533,7 @@ export class SolCoin extends AccountCoinToken {
453533 public tokenAddress : string ;
454534 public contractAddress : string ;
455535 public programId : string ;
536+ public tokenExtensions ?: SolTokenExtensions ;
456537 constructor ( options : SolCoinConstructorOptions ) {
457538 super ( {
458539 ...options ,
@@ -461,6 +542,12 @@ export class SolCoin extends AccountCoinToken {
461542 this . tokenAddress = options . contractAddress ;
462543 this . contractAddress = options . contractAddress ;
463544 this . programId = options . programId ;
545+ this . tokenExtensions = options . tokenExtensions ;
546+ }
547+
548+ /** True if this token was onboarded with the given Token-2022 extension. */
549+ public hasExtension ( type : SolTokenExtensionType ) : boolean {
550+ return this . tokenExtensions ?. detected . includes ( type ) ?? false ;
464551 }
465552}
466553
@@ -2086,7 +2173,8 @@ export function solToken(
20862173 prefix = '' ,
20872174 suffix : string = name . toUpperCase ( ) ,
20882175 network : AccountNetwork = Networks . main . sol ,
2089- primaryKeyCurve : KeyCurve = KeyCurve . Ed25519
2176+ primaryKeyCurve : KeyCurve = KeyCurve . Ed25519 ,
2177+ tokenExtensions ?: SolTokenExtensions
20902178) {
20912179 return Object . freeze (
20922180 new SolCoin ( {
@@ -2105,6 +2193,7 @@ export function solToken(
21052193 isToken : true ,
21062194 primaryKeyCurve,
21072195 baseUnit : BaseUnit . SOL ,
2196+ tokenExtensions,
21082197 } )
21092198 ) ;
21102199}
@@ -2135,7 +2224,9 @@ export function tsolToken(
21352224 programId = ProgramID . TokenProgramId ,
21362225 prefix = '' ,
21372226 suffix : string = name . toUpperCase ( ) ,
2138- network : AccountNetwork = Networks . test . sol
2227+ network : AccountNetwork = Networks . test . sol ,
2228+ primaryKeyCurve : KeyCurve = KeyCurve . Ed25519 ,
2229+ tokenExtensions ?: SolTokenExtensions
21392230) {
21402231 return solToken (
21412232 id ,
@@ -2149,7 +2240,9 @@ export function tsolToken(
21492240 programId ,
21502241 prefix ,
21512242 suffix ,
2152- network
2243+ network ,
2244+ primaryKeyCurve ,
2245+ tokenExtensions
21532246 ) ;
21542247}
21552248
0 commit comments