Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crossmint(SSW): Fixes #438

Merged
merged 3 commits into from
Mar 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
"""
This file contains examples of how to create a Solana Smart Wallet with different configurations and linked users.

To run these examples, you need to set the following environment variables:
- CROSSMINT_API_KEY
- SOLANA_RPC_ENDPOINT
- CROSSMINT_BASE_URL
"""

from goat_wallets.crossmint.solana_smart_wallet_factory import SolanaSmartWalletFactory
from goat_wallets.crossmint.types import SolanaKeypairSigner, SolanaFireblocksSigner
from goat_wallets.crossmint.solana_smart_wallet import SolanaSmartWalletConfig
from goat_wallets.crossmint.solana_smart_wallet import SolanaSmartWalletClient
from goat_wallets.crossmint.api_client import CrossmintWalletsAPI
from solders.keypair import Keypair
from goat_wallets.crossmint.parameters import CoreSignerType
from typing import Literal, Optional
from solana.rpc.api import Client as SolanaClient
import os
from dotenv import load_dotenv
import uuid

load_dotenv()


def create_wallet(factory: SolanaSmartWalletFactory, signer_type: Literal["solana-keypair", "solana-fireblocks-custodial"], linked_user: Optional[str] = None, idempotency_key: Optional[str] = None) -> SolanaSmartWalletClient:
print("=" * 50)
print(
f"\n🔑 Creating Solana Smart Wallet {"idempotently" if idempotency_key or linked_user else ""} with {signer_type} admin signer and linked user {linked_user}...")
print(f"Idempotency key: {idempotency_key}") if idempotency_key else None

config = SolanaSmartWalletConfig(
adminSigner=SolanaKeypairSigner(
type=CoreSignerType.SOLANA_KEYPAIR,
keyPair=Keypair()
) if signer_type == "solana-keypair" else SolanaFireblocksSigner(
type=CoreSignerType.SOLANA_FIREBLOCKS_CUSTODIAL,
)
)
params = {"config": config}
if linked_user:
params["linkedUser"] = linked_user
wallet = factory.get_or_create(params, idempotency_key=idempotency_key)

print(f"✅ Wallet created successfully!")
print(f"📝 Wallet Address: {wallet.get_address()}")
print(
f"👤 Admin Signer: {wallet.get_admin_signer_address()}. Type: {"MPC Custodial" if signer_type == "solana-fireblocks-custodial" else "Non-custodial"}")
return wallet


def main():
print("🚀 Starting Solana Smart Wallet Creation Examples")
api_key = os.getenv("CROSSMINT_API_KEY")
base_url = os.getenv("CROSSMINT_BASE_URL", "https://staging.crossmint.com")
rpc_url = os.getenv("SOLANA_RPC_ENDPOINT", "https://api.devnet.solana.com")
if not api_key:
raise ValueError("❌ CROSSMINT_API_KEY is required")

print("\n🔧 Initializing API client and connection...")
api_client = CrossmintWalletsAPI(api_key, base_url=base_url)
connection = SolanaClient(rpc_url)

print("\n🔧 Initializing factory...")
factory = SolanaSmartWalletFactory(api_client, connection)

# Signer configurations
create_wallet(factory, "solana-keypair")
create_wallet(factory, "solana-fireblocks-custodial")

# Idempotency key configurations (both requests will return the same wallet)
idempotency_key = str(uuid.uuid4())
create_wallet(factory, "solana-fireblocks-custodial",
idempotency_key=idempotency_key)
create_wallet(factory, "solana-fireblocks-custodial",
idempotency_key=idempotency_key)

# Linked user configurations. Creations with the same linked user will return the same wallet.
create_wallet(factory, "solana-keypair", "email:example@example.com")
create_wallet(factory, "solana-fireblocks-custodial",
"phoneNumber:+1234567890")
create_wallet(factory, "solana-keypair", "twitter:example")
create_wallet(factory, "solana-fireblocks-custodial", "userId:1234567890")
create_wallet(factory, "solana-keypair", "x:example")


if __name__ == "__main__":
main()
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@

import os
from goat_wallets.crossmint.solana_smart_wallet import SolanaSmartWalletClient
from goat_wallets.crossmint.parameters import WalletType
from goat_wallets.crossmint.parameters import CoreSignerType
from goat_wallets.crossmint.parameters import AdminSigner
from goat_wallets.crossmint.solana_smart_wallet_factory import SolanaSmartWalletFactory
from goat_wallets.crossmint.types import SolanaKeypairSigner
from goat_wallets.crossmint.solana_smart_wallet import SolanaSmartWalletConfig
from solana.rpc.api import Client as SolanaClient
from goat_wallets.crossmint.api_client import CrossmintWalletsAPI
from goat_wallets.crossmint.solana_smart_wallet_factory import solana_smart_wallet_factory
from solders.keypair import Keypair
from dotenv import load_dotenv
from solders.pubkey import Pubkey
Expand All @@ -24,94 +24,94 @@

load_dotenv()


def create_memo_instruction(fee_payer: Pubkey, memo: str) -> Instruction:
memo_program_id = Pubkey.from_string("MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr")
accounts = [AccountMeta(pubkey=fee_payer, is_signer=False, is_writable=False)]
memo_program_id = Pubkey.from_string(
"MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr")
accounts = [AccountMeta(
pubkey=fee_payer, is_signer=False, is_writable=False)]
data = bytes(memo, "utf-8")
return Instruction(
memo_program_id,
data,
accounts,
)

def create_wallet(api_client: CrossmintWalletsAPI, connection: SolanaClient, signer: Keypair) -> SolanaSmartWalletClient:

def create_wallet(factory: SolanaSmartWalletFactory, signer: Keypair) -> SolanaSmartWalletClient:
print("\n🔑 Creating Solana Smart Wallet...")
wallet_creation_response = api_client.create_smart_wallet(
WalletType.SOLANA_SMART_WALLET,
AdminSigner(
wallet = factory.get_or_create({
"config": SolanaSmartWalletConfig(
adminSigner=SolanaKeypairSigner(
type=CoreSignerType.SOLANA_KEYPAIR,
address=str(signer.pubkey())
),
keyPair=signer
)
)
})
print(f"✅ Wallet created successfully!")
print(f"📝 Wallet Address: {wallet_creation_response['address']}")
print(f"📝 Wallet Address: {wallet.get_address()}")
print(f"👤 Admin Signer: {signer.pubkey()}")
return SolanaSmartWalletClient(
wallet_creation_response["address"],
api_client,
{
"config": {
"adminSigner": {
"type": "solana-keypair",
"keyPair": signer
}
}
},
connection=connection
)
return wallet


def register_delegated_signer(wallet: SolanaSmartWalletClient, signer: Keypair) -> Pubkey:
print("\n🔑 Registering delegated signer...")
delegated_signer_response = wallet.register_delegated_signer(
str(signer.pubkey())
)
print(f"✅ Delegated signer registered successfully!")
print(f"📝 Delegated Signer Locator: {delegated_signer_response['locator']}")
print(
f"📝 Delegated Signer Locator: {delegated_signer_response['locator']}")
print(f"👤 Delegated Signer Address: {signer.pubkey()}")
return delegated_signer_response["locator"]


def send_transaction(wallet: SolanaSmartWalletClient, signer: Keypair):
print("\n💸 Preparing transaction...")
transaction = create_memo_instruction(Pubkey.from_string(wallet.get_address()), "My first Solana Smart Wallet transaction! 🚀")
instruction = create_memo_instruction(Pubkey.from_string(
wallet.get_address()), "My first Solana Smart Wallet transaction! 🚀")
print(f"📝 Transaction Details:")
print(f" From: {wallet.get_address()}")
print(f" Signer: {signer.pubkey()}")
print(f" Message: My first Solana Smart Wallet transaction! 🚀")

print("\n📤 Sending transaction to network...")
transaction_response = wallet.send_transaction(
{
"instructions": [transaction],
"instructions": [instruction],
"signer": signer
}
)
print(f"✅ Transaction sent successfully!")
print(f"🔗 Transaction Hash: {transaction_response.get('hash')}")


def main():
print("🚀 Starting Solana Smart Wallet Delegated Signer Example")
print("=" * 50)

api_key = os.getenv("CROSSMINT_API_KEY")
base_url = os.getenv("CROSSMINT_BASE_URL", "https://staging.crossmint.com")
rpc_url = os.getenv("SOLANA_RPC_ENDPOINT", "https://api.devnet.solana.com")
if not api_key:
raise ValueError("❌ CROSSMINT_API_KEY is required")

print("\n🔧 Initializing API client and connection...")
api_client = CrossmintWalletsAPI(api_key, base_url=base_url)
connection = SolanaClient(rpc_url)

print("\n🔑 Generating keypairs...")
admin_signer = Keypair()
delegated_signer = Keypair()

wallet = create_wallet(api_client, connection, admin_signer)

factory = SolanaSmartWalletFactory(api_client, connection)
wallet = create_wallet(factory, admin_signer)
register_delegated_signer(wallet, delegated_signer)
send_transaction(wallet, delegated_signer)

print("\n✨ Example completed successfully!")
print("=" * 50)


if __name__ == "__main__":
main()
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@

import os
from goat_wallets.crossmint.solana_smart_wallet import SolanaSmartWalletClient
from goat_wallets.crossmint.parameters import WalletType
from goat_wallets.crossmint.parameters import CoreSignerType
from goat_wallets.crossmint.parameters import AdminSigner
from goat_wallets.crossmint.solana_smart_wallet_factory import SolanaSmartWalletFactory
from goat_wallets.crossmint.types import SolanaFireblocksSigner
from goat_wallets.crossmint.solana_smart_wallet import SolanaSmartWalletConfig
from solana.rpc.api import Client as SolanaClient
from goat_wallets.crossmint.api_client import CrossmintWalletsAPI
from dotenv import load_dotenv
Expand All @@ -22,73 +23,74 @@

load_dotenv()


def create_memo_instruction(fee_payer: Pubkey, memo: str) -> Instruction:
memo_program_id = Pubkey.from_string("MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr")
accounts = [AccountMeta(pubkey=fee_payer, is_signer=False, is_writable=False)]
memo_program_id = Pubkey.from_string(
"MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr")
accounts = [AccountMeta(
pubkey=fee_payer, is_signer=False, is_writable=False)]
data = bytes(memo, "utf-8")
return Instruction(
memo_program_id,
data,
accounts,
)

def create_wallet(api_client: CrossmintWalletsAPI, connection: SolanaClient
) -> SolanaSmartWalletClient:

def create_wallet(factory: SolanaSmartWalletFactory) -> SolanaSmartWalletClient:
print("\n🔑 Creating Solana Smart Wallet with Fireblocks custodial signer...")
wallet_creation_response = api_client.create_smart_wallet(
WalletType.SOLANA_SMART_WALLET,
AdminSigner(
wallet = factory.get_or_create({
"config": SolanaSmartWalletConfig(
adminSigner=SolanaFireblocksSigner(
type=CoreSignerType.SOLANA_FIREBLOCKS_CUSTODIAL,
),
)
)
address = wallet_creation_response["address"]
})

print(f"✅ Wallet created successfully!")
print(f"📝 Wallet Address: {address}")
print(f"📝 Wallet Address: {wallet.get_address()}")
print(f"🔐 Signer Type: Fireblocks Custodial")
return SolanaSmartWalletClient(
address,
api_client,
{
"config": {"adminSigner": {"type": "fireblocks"}},
},
connection=connection
)
return wallet


def send_transaction(wallet: SolanaSmartWalletClient):
print("\n💸 Preparing transaction...")
transaction = create_memo_instruction(Pubkey.from_string(wallet.get_address()), "My first Solana Smart Wallet transaction! 🚀")
instruction = create_memo_instruction(Pubkey.from_string(
wallet.get_address()), "My first Solana Smart Wallet transaction! 🚀")
print(f"📝 Transaction Details:")
print(f" From: {wallet.get_address()}")
print(f" Message: My first Solana Smart Wallet transaction! 🚀")

print("\n📤 Sending transaction to network...")
transaction_response = wallet.send_transaction(
{
"instructions": [transaction],
"instructions": [instruction],
}
)
print(f"✅ Transaction sent successfully!")
print(f"🔗 Transaction Hash: {transaction_response.get('hash')}")


def main():
print("🚀 Starting Solana Smart Wallet Fireblocks Signer Example")
print("=" * 50)

api_key = os.getenv("CROSSMINT_API_KEY")
base_url = os.getenv("CROSSMINT_BASE_URL", "https://staging.crossmint.com")
rpc_url = os.getenv("SOLANA_RPC_ENDPOINT", "https://api.devnet.solana.com")
if not api_key:
raise ValueError("❌ CROSSMINT_API_KEY is required")

print("\n🔧 Initializing API client and connection...")
api_client = CrossmintWalletsAPI(api_key, base_url=base_url)
connection = SolanaClient(rpc_url)

wallet = create_wallet(api_client, connection)
wallet = create_wallet(SolanaSmartWalletFactory(api_client, connection))
send_transaction(wallet)

print("\n✨ Example completed successfully!")
print("=" * 50)


if __name__ == "__main__":
main()
Loading