Skip to main content
Defined in the Base Account SDK
Node.js Only: This function uses CDP (Coinbase Developer Platform) and is only available in Node.js environments.
The getOrCreateSubscriptionOwnerWallet function creates or retrieves a CDP smart wallet that acts as the subscription owner (spender). This wallet is used by charge() and revoke() to manage subscriptions from your backend.

How It Works

This function:
  1. Initializes a CDP client with your credentials
  2. Creates or retrieves an EOA (Externally Owned Account) with the specified name
  3. Creates or retrieves a smart wallet owned by that EOA
  4. Returns the smart wallet address (not the EOA address)
Architecture:
CDP Account
  └── EOA (wallet owner)
       └── Smart Wallet (subscription owner) ← This address is returned
The smart wallet address is what you use as the subscriptionOwner parameter when calling subscribe().

Parameters

cdpApiKeyId
string
CDP API key ID. Falls back to CDP_API_KEY_ID environment variable.
cdpApiKeySecret
string
CDP API key secret. Falls back to CDP_API_KEY_SECRET environment variable.
cdpWalletSecret
string
CDP wallet secret. Falls back to CDP_WALLET_SECRET environment variable.
walletName
string
Optional custom wallet name for organization. Default: “subscription owner”
Default Recommended: Most applications should use the default wallet name. The default ensures consistency across all subscription operations automatically.
Custom Wallet Names: If you specify a custom walletName, you must use the exact same name in all subsequent charge() and revoke() calls. Mismatched names will cause operations to fail.

Returns

result
GetOrCreateSubscriptionOwnerWalletResult
Wallet creation result.

Setup

Get CDP credentials from the CDP Portal. Set as environment variables:
export CDP_API_KEY_ID="your-api-key-id"
export CDP_API_KEY_SECRET="your-api-key-secret"
export CDP_WALLET_SECRET="your-wallet-secret"
Or pass directly as parameters (see examples below).
import { base } from '@base-org/account/node';

// Requires: CDP_API_KEY_ID, CDP_API_KEY_SECRET, CDP_WALLET_SECRET env vars
// Uses default wallet name - no need to specify
const wallet = await base.subscription.getOrCreateSubscriptionOwnerWallet();

console.log(`Smart Wallet Address: ${wallet.address}`);
console.log(`Wallet Name: ${wallet.walletName}`); // "subscription owner"
console.log(`EOA Owner: ${wallet.eoaAddress}`);

// Use this address in subscribe calls
const subscription = await base.subscription.subscribe({
  recurringCharge: "9.99",
  subscriptionOwner: wallet.address, // ← Use smart wallet address
  periodInDays: 30
});
{
  address: "0xFe21034794A5a574B94fE4fDfD16e005F1C96e51",
  walletName: "subscription owner",
  eoaAddress: "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb8"
}

Idempotency

This function is idempotent: Calling it multiple times with the same walletName returns the same wallet.
// First call creates the wallet
const wallet1 = await base.subscription.getOrCreateSubscriptionOwnerWallet({
  walletName: 'my-wallet'
});

// Second call returns the same wallet
const wallet2 = await base.subscription.getOrCreateSubscriptionOwnerWallet({
  walletName: 'my-wallet'
});

console.log(wallet1.address === wallet2.address); // true

Error Handling

try {
  const wallet = await base.subscription.getOrCreateSubscriptionOwnerWallet();
  
  console.log(`Wallet ready: ${wallet.address}`);
  
} catch (error) {
  console.error(`Failed to create wallet: ${error.message}`);
  
  if (error.message.includes('CDP credentials')) {
    console.log('Check your CDP_API_KEY_ID, CDP_API_KEY_SECRET, and CDP_WALLET_SECRET');
  }
}

Common Errors

Failed to initialize CDP client for subscription owner wallet
Solution: Ensure environment variables are set:
  • CDP_API_KEY_ID
  • CDP_API_KEY_SECRET
  • CDP_WALLET_SECRET
Or pass them as parameters to the function.Get credentials from CDP Portal.
Failed to get or create subscription owner smart wallet
Solution: Verify your CDP credentials are correct and active in the CDP Portal.

Smart Wallet Benefits

Using a CDP smart wallet as your subscription owner provides several advantages:
The smart wallet handles all transaction details including nonce management, gas estimation, and retries.
Smart wallets support paymasters, allowing you to sponsor gas fees for subscription charges and revocations.
const result = await base.subscription.charge({
  id: subscriptionId,
  amount: 'max-remaining-charge',
  paymasterUrl: 'https://api.developer.coinbase.com/rpc/v1/base/your-key'
});
Smart wallets can batch multiple operations into a single transaction, reducing gas costs and improving efficiency.
CDP manages the private keys securely, reducing the risk of key compromise in your application.

Best Practices

  • Use Environment Variables
  • One-Time Setup
  • Advanced: Multiple Wallets
Store CDP credentials as environment variables instead of hardcoding them:
.env
CDP_API_KEY_ID=your-api-key-id
CDP_API_KEY_SECRET=your-api-key-secret
CDP_WALLET_SECRET=your-wallet-secret
Then use them:
const wallet = await base.subscription.getOrCreateSubscriptionOwnerWallet();
// Automatically uses environment variables

Security Considerations

Keep CDP Credentials Secure
  • Never commit credentials to version control
  • Use environment variables or secret management systems
  • Rotate credentials periodically
  • Restrict CDP API key permissions to only what’s needed
Wallet Address is PublicThe smart wallet address is public and will be visible on-chain. This is expected and safe - users need to know which address they’re granting permissions to.