الترقية من الإصدار 1.x؟ راجع دليل الترحيل إلى 2.0.
التثبيت
قم بتثبيت الحزمة الشاملة أو الموقعين الفرديين حسب الحاجة:
# Umbrella package (includes all signers)pnpm add @solana/keychain# Or install individual packagespnpm add @solana/keychain-core # Core interfaces (required for custom signers)pnpm add @solana/keychain-memory # Local keypair signerpnpm add @solana/keychain-vault # HashiCorp Vaultpnpm add @solana/keychain-aws-kms # AWS KMSpnpm add @solana/keychain-gcp-kms # GCP KMSpnpm add @solana/keychain-privy # Privypnpm add @solana/keychain-turnkey # Turnkeypnpm add @solana/keychain-fireblocks # Fireblockspnpm add @solana/keychain-cdp # Coinbase Developer Platformpnpm add @solana/keychain-crossmint # Crossmintpnpm add @solana/keychain-dfns # Dfnspnpm add @solana/keychain-openfort # Openfortpnpm add @solana/keychain-para # Parapnpm add @solana/keychain-utila # Utilapnpm add @solana/keychain-fordefi # Fordefi# Kit client plugins (keychainSigner / keychainPayer / keychainIdentity)pnpm add @solana/keychain-kit-plugin
يتطلب @solana/kit الإصدار 8.1 أو أحدث. معاملات v1
(createTransactionMessage({ version: 1 })) مدعومة، باستثناء Fireblocks
مع useProgramCall: true، الذي يقبل المعاملات القديمة (legacy) وv0 فقط.
الاستخدام الأساسي
المصنع الموحد (موصى به للتطبيقات التي ترغب في دعم موقعين متعددين)
استخدم createKeychainSigner مع تكوين مميز لإنشاء أي واجهة خلفية:
import { createKeychainSigner } from "@solana/keychain";import { signTransactionWithSigners } from "@solana/signers"; // requires @solana/signers >= 8.1const signer = await createKeychainSigner({backend: "privy",appId: "your-app-id",appSecret: "your-app-secret",walletId: "your-wallet-id"});// Sign an already-compiled transactionconst signedTx = await signTransactionWithSigners([signer],compiledTransaction);
أو قم بتثبيت حزمة موقع فردية للحصول على بصمة تبعيات أصغر:
import { createPrivySigner } from "@solana/keychain-privy";const signer = await createPrivySigner({appId: "your-app-id",appSecret: "your-app-secret",walletId: "your-wallet-id"});
الاستخدام مع رسائل المعاملات
تُرجع كل واجهة خلفية، باستثناء Crossmint ووضع Fordefi الأصلي، كائن
SolanaTransactionSigner، وهو TransactionPartialSigner في Kit ويعمل
مع دوال المساعدة الخاصة بالموقّعين الجزئيين في @solana/signers الموضحة أدناه. تتناول قدرات الموقّع الواجهات الخلفية ذات البث المُدار.
import type { SolanaTransactionSigner } from "@solana/keychain-core";import { signTransactionMessageWithSigners } from "@solana/signers";import {createTransactionMessage,setTransactionMessageFeePayerSigner,pipe} from "@solana/kit";async function signWithKeychain(signer: SolanaTransactionSigner) {// Check availability (useful for remote signers)if (!(await signer.isAvailable())) {throw new Error("Signer offline");}// Use with @solana/kit transaction builderconst transaction = pipe(createTransactionMessage({ version: 0 }),(tx) => setTransactionMessageFeePayerSigner(signer, tx)// ... set a lifetime and add instructions);// Sign with the standard signers APIconst signedTx = await signTransactionMessageWithSigners(transaction);return signedTx;}
التوقيع والإرسال باستخدام أي موقّع
تتولى signAndSendTransaction من @solana/keychain-core إيصال المعاملة إلى
السلسلة أيًّا كان شكل الموقّع. تبثّ الموقّعات المرسِلة عبر مزوّدها؛ أما كل شكل آخر
فيستخدم دالة sendTransaction التي تمررها أنت (لا تعتمد النواة على أي
RPC):
import { signAndSendTransaction } from "@solana/keychain-core";const signature = await signAndSendTransaction(signer, transaction, {sendTransaction: (tx) =>sendAndConfirmTransaction(tx, { commitment: "confirmed" })});
الاستخدام مع عميل Kit (إضافة keychainSigner)
يقوم @solana/keychain-kit-plugin بتثبيت موقّع سلسلة المفاتيح مباشرةً على
عميل Kit، ويربطه بوصفه payer و identity،
مما يُغنيك عن الإعداد اليدوي لـ pipe الموضّح أعلاه:
import { createClient } from "@solana/kit";import { keychainSigner } from "@solana/keychain-kit-plugin";const client = await createClient().use(keychainSigner({backend: "privy",appId: process.env.PRIVY_APP_ID!,appSecret: process.env.PRIVY_APP_SECRET!,walletId: process.env.PRIVY_WALLET_ID!}));client.payer; // SolanaTransactionSigner, also a Kit TransactionPartialSignerclient.identity; // same signer instance
يقبل المكوّن الإضافي الإعداد نفسه الموسوم بالواجهة الخلفية كما في createKeychainSigner،
باستثناء Crossmint ووضع Fordefi الأصلي (عند ضبط chain). تعيد هذه الواجهات كتابة
المعاملة على جهة الخادم، لذا لا يمكنها العمل كـpayer أو
identity للعميل؛ ويرفضها المكوّن الإضافي عند التجميع وأثناء التشغيل. لا تُضمَّن إلا
الواجهة الخلفية التي يوجّه إليها (تُحمَّل حزم الواجهات الخلفية عبر
import() الديناميكي).
استخدم keychainPayer أو keychainIdentity لتعيين دور واحد فقط، ومزج الخلفيات
على عميل واحد:
import { createClient } from "@solana/kit";import { keychainIdentity, keychainPayer } from "@solana/keychain-kit-plugin";const client = await createClient().use(keychainPayer({backend: "memory",privateKeyPath: `${process.env.HOME}/.config/solana/id.json`})).use(keychainIdentity({ backend: "turnkey", ...turnkeyConfig }));
لديك بالفعل SolanaTransactionSigner؟ إنه TransactionPartialSigner
صالح في Kit، لذا يمكنك تثبيته باستخدام
@solana/kit-plugin-signer
بدلًا من ذلك (pnpm add @solana/kit-plugin-signer):
import { createClient } from "@solana/kit";import { signer } from "@solana/kit-plugin-signer";import { createKeychainSigner } from "@solana/keychain";const mySigner = await createKeychainSigner({backend: "vault",...vaultConfig});const client = createClient().use(signer(mySigner));
الإلغاء والبث غير المؤكَّد
تقبل signTransactions وmodifyAndSignTransactions وsignAndSendTransactions و
signMessages جميعها { abortSignal } كوسيط ثانٍ. يؤدي الإلغاء إلى
التوقف عن الانتظار، لكنه لا يتراجع عن عمل قبله المزوّد بالفعل.
في وضع Crossmint ووضع Fordefi الأصلي التلقائي، لا يعني الفشل أن شيئًا لم يصل إلى السلسلة. عندما قد يكون المزوّد قد قبل المعاملة، يكون رمز الخطأ
SignerErrorCode.BROADCAST_UNCONFIRMED ("SIGNER_BROADCAST_UNCONFIRMED").
يُضبط context.providerTransactionId عند قبول الإنشاء، ويحمل
context.idempotencyKey المفتاح المشتق من الرسالة. إعادة إرسال
المعاملة المطابقة بايتًا ببايت آمنة؛ أما المعاملة المعاد بناؤها (مثلًا بـ blockhash جديد) فهي تحويل جديد. تساعد providerMayHaveAccepted(error) و
providerStatus(error) من @solana/keychain-core في تصنيف الخطأ.
تحقق من حالة المعاملة لدى المزوّد قبل إعادة المحاولة.
إعداد الخلفية
الذاكرة
قدّم واحدًا فقط من keyPair أو privateKey أو privateKeyString أو
privateKeyPath:
import { createMemorySigner } from "@solana/keychain-memory";const signer = await createMemorySigner({privateKeyPath: "/path/to/id.json"});
HashiCorp Vault
import { createVaultSigner } from "@solana/keychain-vault";const signer = createVaultSigner({vaultAddr: "https://vault.example.com:8200",vaultToken: "hvs.xxxxx",keyName: "my-solana-key",publicKey: "base58_public_key"});
AWS KMS
import { createAwsKmsSigner } from "@solana/keychain-aws-kms";const signer = createAwsKmsSigner({keyId: "alias/my-solana-key",publicKey: "base58_public_key",region: "us-east-1" // optional});
GCP KMS
import { createGcpKmsSigner } from "@solana/keychain-gcp-kms";const signer = createGcpKmsSigner({keyName:"projects/my-project/locations/us-east1/keyRings/my-ring/cryptoKeys/my-key/cryptoKeyVersions/1",publicKey: "base58_public_key"});
Privy
import { createPrivySigner } from "@solana/keychain-privy";const signer = await createPrivySigner({appId: "app_id",appSecret: "app_secret",walletId: "wallet_id"});
Turnkey
import { createTurnkeySigner } from "@solana/keychain-turnkey";const signer = createTurnkeySigner({apiPublicKey: "api_public_key",apiPrivateKey: "api_private_key",organizationId: "org_id",privateKeyId: "private_key_id",publicKey: "base58_public_key"});
Fireblocks
import { createFireblocksSigner } from "@solana/keychain-fireblocks";const signer = await createFireblocksSigner({apiKey: "api_key",privateKeyPem: "-----BEGIN RSA PRIVATE KEY-----\n...",vaultAccountId: "0",assetId: "SOL" // or "SOL_TEST" for devnet});
CDP (منصة مطوري Coinbase)
import { createCdpSigner } from "@solana/keychain-cdp";const signer = await createCdpSigner({cdpApiKeyId: "api_key_id",cdpApiKeySecret: "api_key_secret",cdpWalletSecret: "wallet_secret",address: "base58_address",network: "solana" // or "solana-devnet"; required for address lookup tables});
Crossmint
import { createCrossmintSigner } from "@solana/keychain-crossmint";const signer = await createCrossmintSigner({apiKey: "api_key",walletLocator: "wallet_locator"});
Crossmint للإرسال فقط. تنفّذ واجهته البرمجية دائمًا المعاملة المعتمدة
على جهة الخادم وتتكفل برسوم الغاز، لذا لا يعرض الموقّع سوى
signAndSendTransactions(): فلا توجد فيه signTransactions() ولا signMessages()،
ولا يمكن تثبيته باستخدام @solana/keychain-kit-plugin. يحدد التوقيع المُرجَع
المعاملة التي أتمّتها Crossmint على السلسلة.
const [signature] = await signer.signAndSendTransactions([transaction]);// or: await signAndSendTransactionMessageWithSigners(transactionMessage);
Dfns
import { createDfnsSigner } from "@solana/keychain-dfns";const signer = await createDfnsSigner({authToken: "auth_token",credId: "cred_id",privateKeyPem: "-----BEGIN EC PRIVATE KEY-----\n...",walletId: "wallet_id"});
Openfort
import { createOpenfortSigner } from "@solana/keychain-openfort";const signer = await createOpenfortSigner({secretKey: "sk_...",walletSecret: "wallet_secret",accountId: "account_id"});
فقرة
import { createParaSigner } from "@solana/keychain-para";const signer = await createParaSigner({apiKey: "api_key",walletId: "wallet_id"});
Utila
يوقّع Utila المعاملات فقط؛ وليس فيه signMessages().
import { createUtilaSigner } from "@solana/keychain-utila";const signer = await createUtilaSigner({serviceAccountEmail: "sa@example.com",serviceAccountPrivateKeyPem: "-----BEGIN PRIVATE KEY-----\n...",vaultId: "vault_id",walletId: "wallet_id",network: "networks/solana-devnet"});
Fordefi
لدى Fordefi ثلاثة أوضاع للتوقيع، تُحدَّد عند الإنشاء بواسطة chain و
pushMode. يعرض كل وضع دالة معاملات واحدة بالضبط، وتوقّع الأوضاع الثلاثة جميعها
الرسائل:
| الوضع | الإعداد | النوع | الدالة |
|---|---|---|---|
| الصندوق الأسود | chain غير مضبوط | FordefiBlackBoxSigner | signTransactions() |
| أصلي تلقائي | chain مضبوط، وpushMode محذوف أو "auto" | FordefiNativeSigner | signAndSendTransactions() |
| أصلي يدوي | chain مضبوط، وpushMode: "manual" | FordefiNativeManualSigner | modifyAndSignTransactions() |
تُوثَّق طلبات API بتوقيع طلب ECDSA P-256: قدّم
مفتاح التوقيع عبر privateKeyPem، أو أبقه في KMS/HSM بتمرير
requestSigner.
الوضع الأصلي التلقائي (موصى به للاستخدام على السلسلة): اضبط chain، وسيتولى Fordefi
توقيع المعاملة وبثّها بنفسه. ولأن Fordefi قد يستبدل
blockhash أو الرسوم قبل التوقيع، فإن الموقّع هو TransactionSendingSigner في Kit:
استخدمه مع
signAndSendTransactionMessageWithSigners، لا مع مسار الموقّع الجزئي الموضح
أعلاه. يقبل الوضع الأصلي التلقائي فقط معاملة غير موقّعة يكون الموقّع الوحيد المطلوب فيها
هو الخزنة، ولا يمكن استخدامه مع @solana/keychain-kit-plugin.
import { createFordefiSigner } from "@solana/keychain-fordefi";import { signAndSendTransactionMessageWithSigners } from "@solana/signers";import { readFileSync } from "node:fs";const signer = await createFordefiSigner({accessToken: process.env.FORDEFI_ACCESS_TOKEN!,vaultId: process.env.FORDEFI_VAULT_ID!,publicKey: process.env.FORDEFI_PUBLIC_KEY!, // Solana vault address (base58)privateKeyPem: readFileSync("./secret/private.pem", "utf8"),chain: "solana_devnet", // or "solana_mainnet"fee: { type: "custom", priority_fee: "1000" } // optional});const signature =await signAndSendTransactionMessageWithSigners(transactionMessage);
الوضع الأصلي اليدوي: اضبط chain وpushMode: "manual". يعيد Fordefi كتابة
الرسالة (blockhash حديث، تعليمات رسوم Compute Budget) ويوقّعها،
لكنه لا يبثّها. تُرجع modifyAndSignTransactions() المعاملة التي
وقّعها Fordefi، وهي تحل محل التي أرسلتها: تابع دائمًا من
المعاملة المُرجَعة. يجب أن يكون Fordefi هو دافع الرسوم وأن يوقّع قبل أي
موقّع آخر مطلوب. لا تُعرض الفروقات في إعادة الكتابة، لذا افحص النتيجة قبل
البث.
import { createFordefiSigner } from "@solana/keychain-fordefi";import { readFileSync } from "node:fs";const signer = await createFordefiSigner({accessToken: process.env.FORDEFI_ACCESS_TOKEN!,vaultId: process.env.FORDEFI_VAULT_ID!,publicKey: process.env.FORDEFI_PUBLIC_KEY!,privateKeyPem: readFileSync("./secret/private.pem", "utf8"),chain: "solana_devnet",pushMode: "manual"});const [signedTransaction] = await signer.modifyAndSignTransactions([transaction]);
وضع الصندوق الأسود: أغفِل chain. يوقِّع Fordefi البايتات الخام دون بثّها؛ وعليك أنت تجميع المعاملة وإرسالها. استخدم هذا الوضع مع خزنة الصندوق الأسود في Fordefi.
import { createFordefiSigner } from "@solana/keychain-fordefi";import { readFileSync } from "node:fs";const signer = await createFordefiSigner({accessToken: process.env.FORDEFI_ACCESS_TOKEN!,vaultId: process.env.FORDEFI_BB_VAULT_ID!,publicKey: process.env.FORDEFI_BB_PUBLIC_KEY!,privateKeyPem: readFileSync("./secret/private.pem", "utf8")});
قدرات الموقّع
تعرّف @solana/keychain-core واجهة واحدة لكل شكل من أشكال موقّعات Kit. تضيف كل منها
isAvailable(): Promise<boolean> إلى واجهة @solana/signers المطابقة:
SolanaTransactionSigner(TransactionPartialSignerفي Kit): يُرجع التوقيعات لمعاملة تملكها.SolanaModifyingSigner(TransactionModifyingSignerفي Kit): يعيد كتابة المعاملة ويوقّعها ويُرجع المعاملة الجديدة دون بثّها.SolanaSendingSigner(TransactionSendingSignerفي Kit): يوقّع ويبثّ عبر مزوّده.SolanaMessageSigner(MessagePartialSignerفي Kit): يوقّع الرسائل خارج السلسلة. وهو منفصل عن أشكال المعاملات.
SolanaSigner هو اتحاد (union) أشكال المعاملات الثلاثة. يسمّي نوع الإرجاع لكل مصنع
الشكل الدقيق لواجهته الخلفية. وعندما لا يُعرف الإعداد إلا
أثناء التشغيل، استخدم التضييق عبر isSolanaTransactionSigner أو isSolanaModifyingSigner أو
isSolanaSendingSigner أو isSolanaMessageSigner. تُبلغ signerCapabilities(signer)
عن الأربعة جميعها دفعة واحدة.
| الواجهة الخلفية | الشكل |
|---|---|
| memory, vault, aws-kms, gcp-kms, privy, turnkey, fireblocks, cdp, dfns, para, openfort, fordefi (الصندوق الأسود) | SolanaTransactionSigner & SolanaMessageSigner |
| utila | SolanaTransactionSigner (دون توقيع الرسائل) |
| fordefi (أصلي يدوي) | SolanaModifyingSigner & SolanaMessageSigner |
| fordefi (أصلي تلقائي) | SolanaSendingSigner & SolanaMessageSigner |
| crossmint | SolanaSendingSigner (دون توقيع الرسائل) |
import {isSolanaSendingSigner,isSolanaTransactionSigner} from "@solana/keychain-core";if (isSolanaSendingSigner(signer)) {await signer.signAndSendTransactions([transaction]);} else if (isSolanaTransactionSigner(signer)) {await signer.signTransactions([transaction]);}
بناء موقّعين مخصصين
نفّذ واجهات القدرات التي تدعمها واجهتك الخلفية:
import type {SolanaMessageSigner,SolanaTransactionSigner} from "@solana/keychain-core";import type { Address } from "@solana/addresses";import type {MessagePartialSignerConfig,SignableMessage,TransactionPartialSignerConfig} from "@solana/signers";import type { Transaction } from "@solana/transactions";class MyCustomSigner implements SolanaTransactionSigner, SolanaMessageSigner {constructor(readonly address: Address) {}async isAvailable(): Promise<boolean> {return await myBackend.healthCheck();}async signMessages(messages: readonly SignableMessage[],config?: MessagePartialSignerConfig) {return await myBackend.signMessages(messages, config?.abortSignal);}async signTransactions(transactions: readonly Transaction[],config?: TransactionPartialSignerConfig) {return await myBackend.signTransactions(transactions, config?.abortSignal);}}
نفّذ فقط ما تدعمه واجهتك الخلفية. يصنّف Kit الموقّعين بحسب الدوال الموجودة، لذا لا تضف أبدًا دالة تكتفي بإطلاق خطأ.
راجع دليل إضافة الموقّعين لدمج خدمات إدارة المفاتيح الإضافية.
Is this page helpful?