diff --git a/.yarn/install-state.gz b/.yarn/install-state.gz index 15962664..a6a0761e 100644 Binary files a/.yarn/install-state.gz and b/.yarn/install-state.gz differ diff --git a/packages/core/components/TopBar/TopBar.tsx b/packages/core/components/TopBar/TopBar.tsx index 72e727f4..5aa691b4 100644 --- a/packages/core/components/TopBar/TopBar.tsx +++ b/packages/core/components/TopBar/TopBar.tsx @@ -8,6 +8,7 @@ import { WalletConnect, xbull, hana, + albedo, } from "@phoenix-protocol/state"; import { AppBar, ConnectWallet } from "@phoenix-protocol/ui"; import React, { useEffect } from "react"; @@ -76,6 +77,7 @@ const TopBar = ({ xbull(), lobstr(), hana(), + albedo(), new WalletConnect(true), ]} setOpen={() => store.setWalletModalOpen(!store.walletModalOpen)} diff --git a/packages/state/package.json b/packages/state/package.json index cd5d1d72..84cd02f6 100644 --- a/packages/state/package.json +++ b/packages/state/package.json @@ -26,6 +26,7 @@ "typescript": "^5.1.3" }, "dependencies": { + "@albedo-link/intent": "^0.12.0", "@lobstrco/signer-extension-api": "^1.0.0-beta.0", "@phoenix-protocol/contracts": "workspace:^", "@stellar/freighter-api": "3.0.0", diff --git a/packages/state/src/index.ts b/packages/state/src/index.ts index 62586c1a..b85c311a 100644 --- a/packages/state/src/index.ts +++ b/packages/state/src/index.ts @@ -4,6 +4,7 @@ export { xbull } from "./state/wallet/xbull"; export { lobstr } from "./state/wallet/lobstr"; export { WalletConnect } from "./state/wallet/wallet-connect"; export { hana } from "./state/wallet/hana"; +export { albedo } from "./state/wallet/albedo"; // Export chains export { diff --git a/packages/state/src/state/persist/createConnectWalletActions.ts b/packages/state/src/state/persist/createConnectWalletActions.ts index f420abe2..f1b54445 100644 --- a/packages/state/src/state/persist/createConnectWalletActions.ts +++ b/packages/state/src/state/persist/createConnectWalletActions.ts @@ -7,6 +7,7 @@ import { xbull } from "../wallet/xbull"; import { lobstr } from "../wallet/lobstr"; import { WalletConnect } from "../wallet/wallet-connect"; import { hana } from "../wallet/hana"; +import { albedo } from "../wallet/albedo"; // Maintain a single WalletConnect instance let walletConnectInstance: WalletConnect | null = null; @@ -100,6 +101,9 @@ export const createConnectWalletActions = () => { case "hana": address = await hana().getPublicKey(); break; + case "albedo": + address = await albedo().getPublicKey(); + break; case "wallet-connect": const Client = await initializeWalletConnect(forceNew); address = await Client.getPublicKey(); diff --git a/packages/state/src/state/wallet/albedo.ts b/packages/state/src/state/wallet/albedo.ts new file mode 100644 index 00000000..1eb99dc3 --- /dev/null +++ b/packages/state/src/state/wallet/albedo.ts @@ -0,0 +1,51 @@ +import freighterApi from "@stellar/freighter-api"; +import { Connector, NetworkDetails } from "@phoenix-protocol/types"; +import albedoSDK from "@albedo-link/intent"; + +export function albedo(): Connector { + return { + id: "albedo", + name: "Albedo", + iconUrl: "https://stellar.creit.tech/wallet-icons/albedo.png", + iconBackground: "#fff", + installed: true, + downloadUrls: { + browserExtension: + "https://chrome.google.com/webstore/detail/freighter/bcacfldlkkdogcmkkibnjlakofdplcbk?hl=en", + }, + async isConnected(): Promise { + return true; // Albedo does not have a direct connection check, so we assume it's always connected + }, + async getNetworkDetails(): Promise { + // !TODO - find a better solution here + return { + ...(await freighterApi.getNetworkDetails()), + networkUrl: + "https://mainnet.stellar.validationcloud.io/v1/YcyPYotN_b6-_656rpr0CabDwlGgkT42NCzPVIqcZh0", + }; + }, + async isAvailable(): Promise { + return true; + }, + async getPublicKey(): Promise { + const result = await albedoSDK.publicKey({}); + return result.pubkey; + }, + async signTransaction( + xdr: string, + opts?: { + network?: string; + networkPassphrase?: string; + accountToSign?: string; + } + ): Promise { + return albedoSDK + .tx({ + xdr, + pubkey: opts?.accountToSign, + network: opts?.networkPassphrase, + }) + .then(({ signed_envelope_xdr }) => signed_envelope_xdr); + }, + }; +} diff --git a/packages/utils/package.json b/packages/utils/package.json index 0c8939c2..27c3b65b 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -26,6 +26,7 @@ "typescript": "^5.1.3" }, "dependencies": { + "@albedo-link/intent": "^0.12.0", "@apollo/client": "^3.9.0", "@creit.tech/xbull-wallet-connect": "0.3.0", "@stellar/stellar-sdk": "^13.1.0", diff --git a/packages/utils/src/trustlines.ts b/packages/utils/src/trustlines.ts index a9f81c04..4af08ae0 100644 --- a/packages/utils/src/trustlines.ts +++ b/packages/utils/src/trustlines.ts @@ -12,6 +12,7 @@ import { xBull } from "./wallets/xbull"; import { lobstr } from "./wallets/lobstr"; import { hana } from "./wallets/hana"; import { Wallet } from "./wallets/types"; +import { Albedo } from "./wallets/albedo"; const horizonUrl = "https://horizon.stellar.org"; const server = new Horizon.Server(horizonUrl); @@ -171,6 +172,10 @@ export async function fetchAndIssueTrustline( case "hana": wallet = new hana(); break; + case "albedo": + wallet = new Albedo(); + break; + case "wallet-connect": // TODO default: wallet = (await import("@stellar/freighter-api")).default; } diff --git a/packages/utils/src/wallets/Signer.ts b/packages/utils/src/wallets/Signer.ts index f518cfda..6ad9fc41 100644 --- a/packages/utils/src/wallets/Signer.ts +++ b/packages/utils/src/wallets/Signer.ts @@ -7,6 +7,7 @@ import { WalletConnectAllowedMethods, } from "./wallet-connect"; import { NETWORK_PASSPHRASE } from "../constants"; +import { Albedo } from "./albedo"; let walletConnectInstance: WalletClient | undefined; const initializeWalletConnect = async () => { if (walletConnectInstance) return walletConnectInstance; @@ -92,6 +93,8 @@ export default class Signer { this.wallet = new lobstr(); } else if (this.walletType === "hana") { this.wallet = new hana(); + } else if (this.walletType === "albedo") { + this.wallet = new Albedo(); } else if (this.walletType === "wallet-connect") { const wc = await initializeWalletConnect(); diff --git a/packages/utils/src/wallets/albedo.ts b/packages/utils/src/wallets/albedo.ts new file mode 100644 index 00000000..83ac67f4 --- /dev/null +++ b/packages/utils/src/wallets/albedo.ts @@ -0,0 +1,96 @@ +import albedo from "@albedo-link/intent"; +import { Wallet } from "./types"; + +/** + * Albedo wallet implementation + * @implements {Wallet} + * @class Albedo + * @export Albedo + * @see {https://github.com/Creit-Tech/Albedo-Wallet} + */ +export class Albedo implements Wallet { + /** + * Check if Albedo is connected + * @returns {Promise} + * @memberof Albedo + * @instance isConnected + */ + async isConnected(): Promise { + return true; + } + + /** + * Check if Albedo is allowed + * @returns {Promise} + * @memberof Albedo + * @instance isAllowed + */ + async isAllowed(): Promise { + return true; + } + + /** + * Get user info from Albedo + * @returns {Promise<{ publicKey?: string }>} + * @memberof Albedo + * @instance getUserInfo + */ + async getAddress(): Promise<{ address?: string }> { + const result = await albedo.publicKey({}); + return { address: result.pubkey }; + } + + /** + * Sign a transaction using Albedo + * @param {string} tx - Transaction XDR + * @param {{ network?: string; networkPassphrase?: string; accountToSign?: string }} [opts] - Options + * @returns {Promise} + * @memberof Albedo + * @instance signTransaction + */ + async signTransaction( + tx: string, + opts?: { + network?: string; + networkPassphrase?: string; + accountToSign?: string; + } + ): Promise<{ + signedTxXdr: string; + signerAddress: string; + }> { + return albedo + .tx({ + xdr: tx, + pubkey: opts?.accountToSign, + network: opts?.networkPassphrase, + }) + .then(({ signed_envelope_xdr }) => ({ + signedTxXdr: signed_envelope_xdr, + signerAddress: opts?.accountToSign || "", + })); + } + + /** + * Sign an authorization entry using Albedo + * @param {string} entryXdr - Authorization entry XDR + * @param {{ accountToSign?: string }} [opts] - Options + * @returns {Promise} + * @memberof Albedo + * @instance signAuthEntry + */ + async signAuthEntry( + entryXdr: string, + opts?: + | { + networkPassphrase?: string | undefined; + address?: string | undefined; + } + | undefined + ): Promise<{ + signedAuthEntry: Buffer | null; + signerAddress: string; + }> { + throw new Error("Albedo does not support signing authorization entries"); + } +} diff --git a/yarn.lock b/yarn.lock index 76e7af6b..5df276e1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12,6 +12,13 @@ __metadata: languageName: node linkType: hard +"@albedo-link/intent@npm:^0.12.0": + version: 0.12.0 + resolution: "@albedo-link/intent@npm:0.12.0" + checksum: 2aece3c1f6624976300ad377eaffa72546d9dfcebd28791b1c1fd6c2bf2774aed080f15d8aa2c5a2408d5f4471b934b01934459f37174bd292969a95efb9fa02 + languageName: node + linkType: hard + "@ampproject/remapping@npm:^2.1.0, @ampproject/remapping@npm:^2.2.0": version: 2.3.0 resolution: "@ampproject/remapping@npm:2.3.0" @@ -3723,6 +3730,7 @@ __metadata: version: 0.0.0-use.local resolution: "@phoenix-protocol/state@workspace:packages/state" dependencies: + "@albedo-link/intent": ^0.12.0 "@lobstrco/signer-extension-api": ^1.0.0-beta.0 "@phoenix-protocol/contracts": "workspace:^" "@phoenix-protocol/types": "workspace:^" @@ -3839,6 +3847,7 @@ __metadata: version: 0.0.0-use.local resolution: "@phoenix-protocol/utils@workspace:packages/utils" dependencies: + "@albedo-link/intent": ^0.12.0 "@apollo/client": ^3.9.0 "@creit.tech/xbull-wallet-connect": 0.3.0 "@phoenix-protocol/types": "*"