diff --git a/intents/intent.gen.go b/intents/intent.gen.go index 18af93c..cd3a6a4 100644 --- a/intents/intent.gen.go +++ b/intents/intent.gen.go @@ -1,4 +1,4 @@ -// sequence-waas-intents v0.1.0 1fe0a24abef81231c54c0886157c65ef738d5ed6 +// sequence-waas-intents v0.1.0 cf2bdd4237ab27bbf05383773801eca35d867b7e // -- // Code generated by webrpc-gen@v0.19.3 with golang generator. DO NOT EDIT. // @@ -25,7 +25,7 @@ func WebRPCSchemaVersion() string { // Schema hash generated from your RIDL schema func WebRPCSchemaHash() string { - return "1fe0a24abef81231c54c0886157c65ef738d5ed6" + return "cf2bdd4237ab27bbf05383773801eca35d867b7e" } // @@ -51,6 +51,7 @@ const ( IntentName_removeAccount IntentName = "removeAccount" IntentName_listAccounts IntentName = "listAccounts" IntentName_getIdToken IntentName = "getIdToken" + IntentName_adoptChildWallet IntentName = "adoptChildWallet" ) func (x IntentName) MarshalText() ([]byte, error) { @@ -125,6 +126,7 @@ const ( IntentResponseCode_accountFederated IntentResponseCode = "accountFederated" IntentResponseCode_accountRemoved IntentResponseCode = "accountRemoved" IntentResponseCode_idToken IntentResponseCode = "idToken" + IntentResponseCode_childwalletAdopted IntentResponseCode = "childwalletAdopted" ) func (x IntentResponseCode) MarshalText() ([]byte, error) { @@ -336,6 +338,18 @@ type IntentDataRemoveAccount struct { AccountID string `json:"accountId"` } +type IntentDataAdoptChildWallet struct { + Network string `json:"network"` + Wallet string `json:"wallet"` + Adopter string `json:"adopter"` + AdopterProof *AdopterProof `json:"adopterProof"` +} + +type AdopterProof struct { + Message string `json:"message"` + Signature string `json:"signature"` +} + type IntentDataGetIdToken struct { SessionID string `json:"sessionId"` Wallet string `json:"wallet"` @@ -499,6 +513,9 @@ type IntentResponseIdToken struct { ExpiresIn int `json:"expiresIn"` } +type IntentResponseChildWalletAdopted struct { +} + type Account struct { ID string `json:"id"` Type IdentityType `json:"type"` diff --git a/intents/intent.gen.ts b/intents/intent.gen.ts index 1a6b9e2..30f8c82 100644 --- a/intents/intent.gen.ts +++ b/intents/intent.gen.ts @@ -1,5 +1,5 @@ /* eslint-disable */ -// sequence-waas-intents v0.1.0 1fe0a24abef81231c54c0886157c65ef738d5ed6 +// sequence-waas-intents v0.1.0 cf2bdd4237ab27bbf05383773801eca35d867b7e // -- // Code generated by webrpc-gen@v0.19.3 with typescript generator. DO NOT EDIT. // @@ -12,7 +12,7 @@ export const WebRPCVersion = "v1" export const WebRPCSchemaVersion = "v0.1.0" // Schema hash generated from your RIDL schema -export const WebRPCSchemaHash = "1fe0a24abef81231c54c0886157c65ef738d5ed6" +export const WebRPCSchemaHash = "cf2bdd4237ab27bbf05383773801eca35d867b7e" // // Types @@ -35,7 +35,8 @@ export enum IntentName { federateAccount = 'federateAccount', removeAccount = 'removeAccount', listAccounts = 'listAccounts', - getIdToken = 'getIdToken' + getIdToken = 'getIdToken', + adoptChildWallet = 'adoptChildWallet' } export enum TransactionType { @@ -63,7 +64,8 @@ export enum IntentResponseCode { accountList = 'accountList', accountFederated = 'accountFederated', accountRemoved = 'accountRemoved', - idToken = 'idToken' + idToken = 'idToken', + childwalletAdopted = 'childwalletAdopted' } export enum FeeTokenType { @@ -188,6 +190,18 @@ export interface IntentDataRemoveAccount { accountId: string } +export interface IntentDataAdoptChildWallet { + network: string + wallet: string + adopter: string + adopterProof: AdopterProof +} + +export interface AdopterProof { + message: string + signature: string +} + export interface IntentDataGetIdToken { sessionId: string wallet: string @@ -350,6 +364,9 @@ export interface IntentResponseIdToken { expiresIn: number } +export interface IntentResponseChildWalletAdopted { +} + export interface Account { id: string type: IdentityType diff --git a/intents/intent.ridl b/intents/intent.ridl index de41759..f15f41d 100644 --- a/intents/intent.ridl +++ b/intents/intent.ridl @@ -34,6 +34,7 @@ enum IntentName: string - removeAccount - listAccounts - getIdToken + - adoptChildWallet struct IntentDataInitiateAuth - sessionId: string @@ -141,6 +142,16 @@ struct IntentDataRemoveAccount - accountId: string + go.field.name = AccountID +struct IntentDataAdoptChildWallet + - network: string + - wallet: string + - adopter: string + - adopterProof: AdopterProof + +struct AdopterProof + - message: string + - signature: string + struct IntentDataGetIdToken - sessionId: string + go.field.name = SessionID @@ -216,6 +227,7 @@ enum IntentResponseCode: string - accountFederated - accountRemoved - idToken + - childwalletAdopted struct IntentResponseAuthInitiated - sessionId: string @@ -318,6 +330,8 @@ struct IntentResponseIdToken - idToken: string - expiresIn: int +struct IntentResponseChildWalletAdopted + enum IdentityType: string - None - Guest diff --git a/intents/intent_response_typed.go b/intents/intent_response_typed.go index 2591c9a..cf42ae9 100644 --- a/intents/intent_response_typed.go +++ b/intents/intent_response_typed.go @@ -36,6 +36,8 @@ func IntentResponseTypeToCode[T any](t *T) IntentResponseCode { return IntentResponseCode_accountFederated case *IntentResponseAccountRemoved: return IntentResponseCode_accountRemoved + case *IntentResponseChildWalletAdopted: + return IntentResponseCode_childwalletAdopted case *IntentResponseIdToken: return IntentResponseCode_idToken default: diff --git a/intents/intent_typed.go b/intents/intent_typed.go index 6fc89d5..c7b9f6f 100644 --- a/intents/intent_typed.go +++ b/intents/intent_typed.go @@ -39,6 +39,8 @@ func IntentDataTypeToName[T any](t *T) IntentName { return IntentName_federateAccount case *IntentDataRemoveAccount: return IntentName_removeAccount + case *IntentDataAdoptChildWallet: + return IntentName_adoptChildWallet case *IntentDataGetIdToken: return IntentName_getIdToken default: diff --git a/sessions/proto/sessions.gen.go b/sessions/proto/sessions.gen.go index aae0dda..7b73a65 100644 --- a/sessions/proto/sessions.gen.go +++ b/sessions/proto/sessions.gen.go @@ -1,6 +1,6 @@ -// sessions v0.0.1 d81ea64cbe41c1ab8b0107bce2f118817b34ebc0 +// sessions v0.0.1 994be64b88246335bece5845145cd079e64f43a5 // -- -// Code generated by webrpc-gen@v0.18.6 with golang generator. DO NOT EDIT. +// Code generated by webrpc-gen@v0.19.3 with golang generator. DO NOT EDIT. // // webrpc-gen -schema=sessions.ridl -target=golang -pkg=proto -server -client -out=./sessions.gen.go package proto @@ -32,7 +32,7 @@ func WebRPCSchemaVersion() string { // Schema hash generated from your RIDL schema func WebRPCSchemaHash() string { - return "d81ea64cbe41c1ab8b0107bce2f118817b34ebc0" + return "994be64b88246335bece5845145cd079e64f43a5" } // @@ -85,22 +85,25 @@ func (x *SignatureType) Is(values ...SignatureType) bool { } type RuntimeStatus struct { - Healthy bool `json:"healthy"` - Started time.Time `json:"started"` - Uptime uint64 `json:"uptime"` - Version string `json:"version"` - Branch string `json:"branch"` - Commit string `json:"commit"` + Healthy bool `json:"healthy"` + Started time.Time `json:"started"` + Uptime uint64 `json:"uptime"` + Version string `json:"version"` + Branch string `json:"branch"` + Commit string `json:"commit"` +} + +type Info struct { Wallets map[string]uint64 `json:"wallets"` Configs map[string]uint64 `json:"configs"` ConfigTrees uint64 `json:"configTrees"` Migrations map[string]uint64 `json:"migrations"` Signatures uint64 `json:"signatures"` Digests uint64 `json:"digests"` - Recorder *RecorderStatus `json:"recorder"` + Recorder *RecorderInfo `json:"recorder"` } -type RecorderStatus struct { +type RecorderInfo struct { Requests uint64 `json:"requests"` Buffer uint64 `json:"buffer"` LastFlush *time.Time `json:"lastFlush"` @@ -118,11 +121,20 @@ type Context struct { } type Signature struct { - Digest prototyp.Hash `json:"digest"` - ToImageHash prototyp.HashMaybe `json:"toImageHash,omitempty"` - ChainID prototyp.BigInt `json:"chainID"` - Type SignatureType `json:"type"` - Signature prototyp.Hash `json:"signature"` + Digest prototyp.Hash `json:"digest"` + ToImageHash prototyp.HashMaybe `json:"toImageHash,omitempty"` + ChainID prototyp.BigInt `json:"chainID"` + Type SignatureType `json:"type"` + Signature prototyp.Hash `json:"signature"` + ValidOnChain *prototyp.BigInt `json:"validOnChain,omitempty"` + ValidOnBlock *prototyp.BigInt `json:"validOnBlock,omitempty"` + ValidOnBlockHash prototyp.HashMaybe `json:"validOnBlockHash,omitempty"` +} + +type SignerSignature struct { + ReferenceChainID *string `json:"referenceChainID"` + Signer *string `json:"signer"` + Signature string `json:"signature"` } type ConfigUpdate struct { @@ -158,6 +170,7 @@ var WebRPCServices = map[string][]string{ "SaveWallet", "SaveSignature", "SaveSignerSignatures", + "SaveSignerSignatures2", "SaveMigration", }, } @@ -169,7 +182,7 @@ var WebRPCServices = map[string][]string{ type Sessions interface { Ping(ctx context.Context) error Config(ctx context.Context, imageHash string) (int, interface{}, error) - Wallets(ctx context.Context, signer string) (map[string]*Signature, error) + Wallets(ctx context.Context, signer string, cursor *uint64, limit *uint64) (map[string]*Signature, uint64, error) DeployHash(ctx context.Context, wallet string) (string, *Context, error) ConfigUpdates(ctx context.Context, wallet string, fromImageHash string, allUpdates *bool) ([]*ConfigUpdate, error) Migrations(ctx context.Context, wallet string, fromVersion int, fromImageHash string, chainID *string) (map[string]map[int]map[string]*TransactionBundle, error) @@ -177,6 +190,7 @@ type Sessions interface { SaveWallet(ctx context.Context, version int, deployConfig interface{}) error SaveSignature(ctx context.Context, wallet string, digest string, chainID string, signature string, toConfig *interface{}) error SaveSignerSignatures(ctx context.Context, wallet string, digest string, chainID string, signatures []string, toConfig *interface{}) error + SaveSignerSignatures2(ctx context.Context, wallet string, digest string, chainID string, signatures []*SignerSignature, toConfig *interface{}) error SaveMigration(ctx context.Context, wallet string, fromVersion int, toVersion int, toConfig interface{}, executor string, transactions []*Transaction, nonce string, signature string, chainID *string) error } @@ -187,7 +201,7 @@ type Sessions interface { type SessionsClient interface { Ping(ctx context.Context) error Config(ctx context.Context, imageHash string) (int, interface{}, error) - Wallets(ctx context.Context, signer string) (map[string]*Signature, error) + Wallets(ctx context.Context, signer string, cursor *uint64, limit *uint64) (map[string]*Signature, uint64, error) DeployHash(ctx context.Context, wallet string) (string, *Context, error) ConfigUpdates(ctx context.Context, wallet string, fromImageHash string, allUpdates *bool) ([]*ConfigUpdate, error) Migrations(ctx context.Context, wallet string, fromVersion int, fromImageHash string, chainID *string) (map[string]map[int]map[string]*TransactionBundle, error) @@ -195,6 +209,7 @@ type SessionsClient interface { SaveWallet(ctx context.Context, version int, deployConfig interface{}) error SaveSignature(ctx context.Context, wallet string, digest string, chainID string, signature string, toConfig *interface{}) error SaveSignerSignatures(ctx context.Context, wallet string, digest string, chainID string, signatures []string, toConfig *interface{}) error + SaveSignerSignatures2(ctx context.Context, wallet string, digest string, chainID string, signatures []*SignerSignature, toConfig *interface{}) error SaveMigration(ctx context.Context, wallet string, fromVersion int, toVersion int, toConfig interface{}, executor string, transactions []*Transaction, nonce string, signature string, chainID *string) error } @@ -253,6 +268,8 @@ func (s *sessionsServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { handler = s.serveSaveSignatureJSON case "/rpc/Sessions/SaveSignerSignatures": handler = s.serveSaveSignerSignaturesJSON + case "/rpc/Sessions/SaveSignerSignatures2": + handler = s.serveSaveSignerSignatures2JSON case "/rpc/Sessions/SaveMigration": handler = s.serveSaveMigrationJSON default: @@ -357,7 +374,9 @@ func (s *sessionsServer) serveWalletsJSON(ctx context.Context, w http.ResponseWr defer r.Body.Close() reqPayload := struct { - Arg0 string `json:"signer"` + Arg0 string `json:"signer"` + Arg1 *uint64 `json:"cursor"` + Arg2 *uint64 `json:"limit"` }{} if err := json.Unmarshal(reqBody, &reqPayload); err != nil { s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCause(fmt.Errorf("failed to unmarshal request data: %w", err))) @@ -365,7 +384,7 @@ func (s *sessionsServer) serveWalletsJSON(ctx context.Context, w http.ResponseWr } // Call service method implementation. - ret0, err := s.Sessions.Wallets(ctx, reqPayload.Arg0) + ret0, ret1, err := s.Sessions.Wallets(ctx, reqPayload.Arg0, reqPayload.Arg1, reqPayload.Arg2) if err != nil { rpcErr, ok := err.(WebRPCError) if !ok { @@ -377,7 +396,8 @@ func (s *sessionsServer) serveWalletsJSON(ctx context.Context, w http.ResponseWr respPayload := struct { Ret0 map[string]*Signature `json:"wallets"` - }{ret0} + Ret1 uint64 `json:"cursor"` + }{ret0, ret1} respBody, err := json.Marshal(respPayload) if err != nil { s.sendErrorJSON(w, r, ErrWebrpcBadResponse.WithCause(fmt.Errorf("failed to marshal json response: %w", err))) @@ -670,6 +690,44 @@ func (s *sessionsServer) serveSaveSignerSignaturesJSON(ctx context.Context, w ht w.Write([]byte("{}")) } +func (s *sessionsServer) serveSaveSignerSignatures2JSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { + ctx = context.WithValue(ctx, MethodNameCtxKey, "SaveSignerSignatures2") + + reqBody, err := io.ReadAll(r.Body) + if err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCause(fmt.Errorf("failed to read request data: %w", err))) + return + } + defer r.Body.Close() + + reqPayload := struct { + Arg0 string `json:"wallet"` + Arg1 string `json:"digest"` + Arg2 string `json:"chainID"` + Arg3 []*SignerSignature `json:"signatures"` + Arg4 *interface{} `json:"toConfig"` + }{} + if err := json.Unmarshal(reqBody, &reqPayload); err != nil { + s.sendErrorJSON(w, r, ErrWebrpcBadRequest.WithCause(fmt.Errorf("failed to unmarshal request data: %w", err))) + return + } + + // Call service method implementation. + err = s.Sessions.SaveSignerSignatures2(ctx, reqPayload.Arg0, reqPayload.Arg1, reqPayload.Arg2, reqPayload.Arg3, reqPayload.Arg4) + if err != nil { + rpcErr, ok := err.(WebRPCError) + if !ok { + rpcErr = ErrWebrpcEndpoint.WithCause(err) + } + s.sendErrorJSON(w, r, rpcErr) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write([]byte("{}")) +} + func (s *sessionsServer) serveSaveMigrationJSON(ctx context.Context, w http.ResponseWriter, r *http.Request) { ctx = context.WithValue(ctx, MethodNameCtxKey, "SaveMigration") @@ -745,12 +803,12 @@ const SessionsPathPrefix = "/rpc/Sessions/" type sessionsClient struct { client HTTPClient - urls [11]string + urls [12]string } func NewSessionsClient(addr string, client HTTPClient) SessionsClient { prefix := urlBase(addr) + SessionsPathPrefix - urls := [11]string{ + urls := [12]string{ prefix + "Ping", prefix + "Config", prefix + "Wallets", @@ -761,6 +819,7 @@ func NewSessionsClient(addr string, client HTTPClient) SessionsClient { prefix + "SaveWallet", prefix + "SaveSignature", prefix + "SaveSignerSignatures", + prefix + "SaveSignerSignatures2", prefix + "SaveMigration", } return &sessionsClient{ @@ -802,12 +861,15 @@ func (c *sessionsClient) Config(ctx context.Context, imageHash string) (int, int return out.Ret0, out.Ret1, err } -func (c *sessionsClient) Wallets(ctx context.Context, signer string) (map[string]*Signature, error) { +func (c *sessionsClient) Wallets(ctx context.Context, signer string, cursor *uint64, limit *uint64) (map[string]*Signature, uint64, error) { in := struct { - Arg0 string `json:"signer"` - }{signer} + Arg0 string `json:"signer"` + Arg1 *uint64 `json:"cursor"` + Arg2 *uint64 `json:"limit"` + }{signer, cursor, limit} out := struct { Ret0 map[string]*Signature `json:"wallets"` + Ret1 uint64 `json:"cursor"` }{} resp, err := doHTTPRequest(ctx, c.client, c.urls[2], in, &out) @@ -818,7 +880,7 @@ func (c *sessionsClient) Wallets(ctx context.Context, signer string) (map[string } } - return out.Ret0, err + return out.Ret0, out.Ret1, err } func (c *sessionsClient) DeployHash(ctx context.Context, wallet string) (string, *Context, error) { @@ -958,6 +1020,26 @@ func (c *sessionsClient) SaveSignerSignatures(ctx context.Context, wallet string return err } +func (c *sessionsClient) SaveSignerSignatures2(ctx context.Context, wallet string, digest string, chainID string, signatures []*SignerSignature, toConfig *interface{}) error { + in := struct { + Arg0 string `json:"wallet"` + Arg1 string `json:"digest"` + Arg2 string `json:"chainID"` + Arg3 []*SignerSignature `json:"signatures"` + Arg4 *interface{} `json:"toConfig"` + }{wallet, digest, chainID, signatures, toConfig} + + resp, err := doHTTPRequest(ctx, c.client, c.urls[10], in, nil) + if resp != nil { + cerr := resp.Body.Close() + if err == nil && cerr != nil { + err = ErrWebrpcRequestFailed.WithCause(fmt.Errorf("failed to close response body: %w", cerr)) + } + } + + return err +} + func (c *sessionsClient) SaveMigration(ctx context.Context, wallet string, fromVersion int, toVersion int, toConfig interface{}, executor string, transactions []*Transaction, nonce string, signature string, chainID *string) error { in := struct { Arg0 string `json:"wallet"` @@ -971,7 +1053,7 @@ func (c *sessionsClient) SaveMigration(ctx context.Context, wallet string, fromV Arg8 *string `json:"chainID"` }{wallet, fromVersion, toVersion, toConfig, executor, transactions, nonce, signature, chainID} - resp, err := doHTTPRequest(ctx, c.client, c.urls[10], in, nil) + resp, err := doHTTPRequest(ctx, c.client, c.urls[11], in, nil) if resp != nil { cerr := resp.Body.Close() if err == nil && cerr != nil { @@ -1037,6 +1119,12 @@ func doHTTPRequest(ctx context.Context, client HTTPClient, url string, in, out i return nil, ErrWebrpcRequestFailed.WithCause(fmt.Errorf("could not build request: %w", err)) } + curl, err := RequestToCurl(req) + if err != nil { + return nil, ErrWebrpcRequestFailed.WithCause(fmt.Errorf("could not convert request to curl: %w", err)) + } + fmt.Println(curl) + resp, err := client.Do(req) if err != nil { return nil, ErrWebrpcRequestFailed.WithCause(err) @@ -1215,5 +1303,45 @@ var ( // Schema errors var ( ErrInvalidArgument = WebRPCError{Code: 1, Name: "InvalidArgument", Message: "invalid argument", HTTPStatus: 400} - ErrNotFound = WebRPCError{Code: 2, Name: "NotFound", Message: "not found", HTTPStatus: 404} + ErrNotFound = WebRPCError{Code: 2, Name: "NotFound", Message: "not found", HTTPStatus: 400} ) + +// RequestToCurl generates a curl command from an http.Request +func RequestToCurl(req *http.Request) (string, error) { + // Start building the curl command + var curlCmd strings.Builder + curlCmd.WriteString("curl -X ") + curlCmd.WriteString(req.Method) + + // Add headers to the curl command + for key, values := range req.Header { + for _, value := range values { + curlCmd.WriteString(fmt.Sprintf(" -H \"%s: %s\"", key, value)) + } + } + + // Add body if the method requires it (e.g., POST, PUT) + if req.Body != nil && (req.Method == http.MethodPost || req.Method == http.MethodPut || req.Method == http.MethodPatch) { + var bodyBytes []byte + var err error + if req.Body != nil { + // Read the body into bytes + bodyBytes, err = io.ReadAll(req.Body) + if err != nil { + return "", err + } + // Restore the body to the request so it can still be used + req.Body = io.NopCloser(bytes.NewBuffer(bodyBytes)) + } + + // If there's a non-empty body, add it to the curl command + if len(bodyBytes) > 0 { + curlCmd.WriteString(fmt.Sprintf(" --data '%s'", string(bodyBytes))) + } + } + + // Add the request URL + curlCmd.WriteString(fmt.Sprintf(" \"%s\"", req.URL.String())) + + return curlCmd.String(), nil +} diff --git a/wallet.go b/wallet.go index 42d6120..82d94bc 100644 --- a/wallet.go +++ b/wallet.go @@ -10,6 +10,7 @@ import ( "github.com/0xsequence/ethkit/ethtxn" "github.com/0xsequence/ethkit/go-ethereum/common" "github.com/0xsequence/ethkit/go-ethereum/core/types" + "github.com/0xsequence/go-sequence/core" v1 "github.com/0xsequence/go-sequence/core/v1" v2 "github.com/0xsequence/go-sequence/core/v2" @@ -462,6 +463,8 @@ func (w *Wallet[C]) SignDigest(ctx context.Context, digest common.Hash, optChain return nil, fmt.Errorf("SignDigest, subDigestOf: %w", err) } + fmt.Println("PARENT SignDigest: ", common.Bytes2Hex(subDigest)) + sign := func(ctx context.Context, signerAddress common.Address, signatures []core.SignerSignature) (core.SignerSignatureType, []byte, error) { signer, _ := w.GetSigner(signerAddress)