55 "context"
66 "errors"
77 "fmt"
8+ "regexp"
89
910 "github.com/Masterminds/semver/v3"
1011 "github.com/ethereum/go-ethereum/accounts/abi/bind"
@@ -679,8 +680,22 @@ func CreateTokenMultisig(e cldf.Environment, cfg CreateTokenMultisigConfig) (cld
679680 return cldf.ChangesetOutput {}, err
680681 }
681682 newMultisig , err := createMultisig (e , tokenPoolSignerPDA , cfg .CustomerMintAuthorities , tokenProgramId )
682- e .Logger .Info ("created multisig" , "newMultisig" , newMultisig )
683- return cldf.ChangesetOutput {}, nil
683+ if err != nil {
684+ return cldf.ChangesetOutput {}, err
685+ }
686+ newAddresses := cldf .NewMemoryAddressBook ()
687+ tv := cldf .NewTypeAndVersion ("TokenMultisig" , deployment .Version1_0_0 )
688+ tv .AddLabel (cfg .Metadata )
689+ tv .AddLabel (cfg .TokenMint .String ())
690+ err = newAddresses .Save (cfg .ChainSelector , newMultisig .String (), tv )
691+ if err != nil {
692+ e .Logger .Errorw ("Failed to save new token multisig" , "chain" , solChainState , "err" , err )
693+ return cldf.ChangesetOutput {}, err
694+ }
695+ e .Logger .Infow ("Created multisig" , "TokenMultisigAddress" , newMultisig , "TokenMint" , cfg .TokenMint , "Signers 1 of" , tokenPoolSignerPDA , cfg .CustomerMintAuthorities )
696+ return cldf.ChangesetOutput {
697+ AddressBook : newAddresses ,
698+ }, nil
684699}
685700
686701func createMultisig (e cldf.Environment , tokenPoolSignerPDA solana.PublicKey , customerMintAuthorities []solana.PublicKey , tokenProgramId solana.PublicKey ) (solana.PublicKey , error ) {
@@ -698,9 +713,25 @@ func createMultisig(e cldf.Environment, tokenPoolSignerPDA solana.PublicKey, cus
698713 e .Logger .Debugw ("spl-token create-multisig error" , "error" , err )
699714 return solana.PublicKey {}, fmt .Errorf ("error spl-token create-multisig: %w" , err )
700715 }
716+ multisigAddress , err := parseMultisigAddress (output )
717+ if err != nil {
718+ e .Logger .Debugw ("spl-token create-multisig error" , "error" , err )
719+ }
701720 e .Logger .Infow ("Created Token Multisig " , "tokenProgramId" , tokenProgramId )
702- // TODO: return output, nil
703- return solana.PublicKey {}, nil
721+ return solana .MustPublicKeyFromBase58 (multisigAddress ), nil
722+ }
723+
724+ // ParseMultisigAddress extracts the created multisig address from either a JSON blob
725+ // with an "output" field or from raw text. It returns the first match it finds.
726+ func parseMultisigAddress (text string ) (string , error ) {
727+ // Regex: captures a Solana base58 address between "multisig" and "under program".
728+ // Solana addresses are base58 (no 0, O, I, l) and typically 32–44 chars.
729+ re := regexp .MustCompile (`(?i)Creating\s+\d+/\d+\s+multisig\s+([1-9A-HJ-NP-Za-km-z]{32,44})\s+under\s+program` )
730+ m := re .FindStringSubmatch (text )
731+ if len (m ) < 2 {
732+ return "" , errors .New ("multisig address not found" )
733+ }
734+ return m [1 ], nil
704735}
705736
706737func ModifyMintAuthority (e cldf.Environment , cfg NewMintTokenPoolConfig ) (cldf.ChangesetOutput , error ) {
0 commit comments