Skip to content

Commit

Permalink
Merge branch 'feat/wallet-connect-v2' into beta
Browse files Browse the repository at this point in the history
  • Loading branch information
yasincaliskan committed Sep 16, 2024
1 parent 9c92e3a commit c0ef46f
Show file tree
Hide file tree
Showing 11 changed files with 2,253 additions and 1,924 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ idea
.vscode
node_modules
dist
build

# misc
.DS_Store
Expand Down
3,888 changes: 2,079 additions & 1,809 deletions package-lock.json

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "2.0.16",
"version": "2.0.17",
"name": "@perawallet/connect-beta",
"description": "Beta version of Pera Wallet Connect",
"main": "dist/index.js",
Expand Down Expand Up @@ -37,9 +37,9 @@
"dependencies": {
"@evanhahn/lottie-web-light": "5.8.1",
"@json-rpc-tools/utils": "1.7.6",
"@walletconnect/sign-client": "2.13.1",
"@walletconnect/types": "2.13.1",
"@walletconnect/utils": "2.13.1",
"@walletconnect/sign-client": "2.16.1",
"@walletconnect/types": "2.16.1",
"@walletconnect/utils": "2.16.1",
"bowser": "2.11.0",
"buffer": "^6.0.3",
"qr-code-styling": "1.6.0-rc.1"
Expand Down
223 changes: 124 additions & 99 deletions src/PeraWalletConnect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@ import {
resetWalletDetailsFromStorage
} from "./util/storage/storageUtils";
import {getPeraConnectConfig} from "./util/api/peraWalletConnectApi";
import {PeraWalletArbitraryData, PeraWalletTransaction, SignerTransaction} from "./util/model/peraWalletModels";
import {
PeraWalletArbitraryData,
PeraWalletTransaction,
SignerTransaction
} from "./util/model/peraWalletModels";
import {
base64ToUint8Array,
composeTransaction,
Expand All @@ -33,7 +37,11 @@ import {isMobile} from "./util/device/deviceUtils";
import {AlgorandChainIDs, PeraWalletNetwork} from "./util/peraWalletTypes";
import {runWebSignTransactionFlow} from "./util/sign/signTransactionFlow";
import {PERA_WALLET_LOCAL_STORAGE_KEYS} from "./util/storage/storageConstants";
import {AlgorandChainNamespace, AlgorandMethod, getPeraWebWalletURL} from "./util/peraWalletConstants";
import {
AlgorandChainNamespace,
AlgorandMethod,
getPeraWebWalletURL
} from "./util/peraWalletConstants";
import appTellerManager, {PeraTeller} from "./util/network/teller/appTellerManager";
import {getMetaInfo, waitForTabOpening} from "./util/dom/domUtils";
import {formatWalletConnectSessionResponse} from "./util/wallet-connect/walletConnectUtils";
Expand All @@ -45,6 +53,7 @@ interface PeraWalletConnectOptions {
chainId?: AlgorandChainIDs;
compactMode?: boolean;
debugger?: boolean;
singleAccount?: boolean;
}

class PeraWalletConnect {
Expand All @@ -55,10 +64,12 @@ class PeraWalletConnect {
projectId?: string;
chainId?: number;
compactMode?: boolean;
singleAccount?: boolean;
debugger?: boolean;

constructor(options: PeraWalletConnectOptions) {
this.projectId = options.projectId;
this.singleAccount = options.singleAccount;
this.debugger = options.debugger;

if (options?.network) {
Expand Down Expand Up @@ -87,6 +98,10 @@ class PeraWalletConnect {
return getWalletPlatformFromStorage();
}

get isPeraDiscoverBrowser() {
return this.checkIsPeraDiscoverBrowser();
}

get isConnected() {
if (this.platform === "mobile" || this.platform === "web") {
return !!getWalletDetailsFromStorage()?.accounts.length;
Expand All @@ -99,91 +114,17 @@ class PeraWalletConnect {
return getWalletDetailsFromStorage()?.accounts;
}

private connectWithWebWallet(
resolve: (accounts: string[]) => void,
reject: (reason?: any) => void,
webWalletURL: string,
chainId: number | undefined
) {
const webWalletURLs = getPeraWebWalletURL(webWalletURL);

function onWebWalletConnect() {
waitForTabOpening(webWalletURLs.CONNECT).then((newPeraWalletTab) => {
if (newPeraWalletTab && newPeraWalletTab.opener) {
appTellerManager.sendMessage({
message: {
type: "CONNECT",
data: {
...getMetaInfo(),
chainId
}
},

origin: webWalletURLs.CONNECT,
targetWindow: newPeraWalletTab,
timeout: 5000
});
}

const checkTabIsAliveInterval = setInterval(() => {
if (newPeraWalletTab?.closed === true) {
reject(
new PeraWalletConnectError(
{
type: "CONNECT_CANCELLED"
},
"Connect is cancelled by user"
)
);

clearInterval(checkTabIsAliveInterval);
onClose();
}

// eslint-disable-next-line no-magic-numbers
}, 2000);

appTellerManager.setupListener({
onReceiveMessage: (event: MessageEvent<TellerMessage<PeraTeller>>) => {
if (resolve && event.data.message.type === "CONNECT_CALLBACK") {
const accounts = event.data.message.data.addresses;

saveWalletDetailsToStorage(accounts, "pera-wallet-web");

resolve(accounts);

onClose();

newPeraWalletTab?.close();
} else if (event.data.message.type === "CONNECT_NETWORK_MISMATCH") {
reject(
new PeraWalletConnectError(
{
type: "CONNECT_NETWORK_MISMATCH",
detail: event.data.message.error
},
event.data.message.error ||
`Your wallet is connected to a different network to this dApp. Update your wallet to the correct network (MainNet or TestNet) to continue.`
)
);

onClose();
private checkIsPeraDiscoverBrowser() {
const userAget = window.navigator.userAgent;

newPeraWalletTab?.close();
}
}
});
});
}

function onClose() {
removeModalWrapperFromDOM(PERA_WALLET_CONNECT_MODAL_ID);
}

return onWebWalletConnect;
return userAget.includes("pera");
}

connect({network}: {network?: PeraWalletNetwork} = {}) {
// `selectedAccount` option is only applicable for Pera Wallet products
connect({
network,
selectedAccount
}: {network?: PeraWalletNetwork; selectedAccount?: string} = {}) {
return new Promise<string[]>(async (resolve, reject) => {
try {
if (network) {
Expand Down Expand Up @@ -218,14 +159,8 @@ class PeraWalletConnect {
const {uri, approval} = await this.client.connect({
requiredNamespaces: {
algorand: {
chains: [
AlgorandChainNamespace.Mainnet,
AlgorandChainNamespace.Testnet
],
methods: [
AlgorandMethod.SignTransaction,
AlgorandMethod.SignData
],
chains: [AlgorandChainNamespace.Mainnet, AlgorandChainNamespace.Testnet],
methods: [AlgorandMethod.SignTransaction, AlgorandMethod.SignData],
events: []
}
}
Expand All @@ -238,7 +173,9 @@ class PeraWalletConnect {
shouldDisplayNewBadge,
shouldUseSound,
compactMode: this.compactMode,
promoteMobile
promoteMobile,
singleAccount: this.singleAccount,
selectedAccount
});

const peraWalletConnectModalWrapper = document.getElementById(
Expand Down Expand Up @@ -443,10 +380,96 @@ class PeraWalletConnect {
});
}

private connectWithWebWallet(
resolve: (accounts: string[]) => void,
reject: (reason?: any) => void,
webWalletURL: string,
chainId: number | undefined
) {
const webWalletURLs = getPeraWebWalletURL(webWalletURL);

function onWebWalletConnect() {
waitForTabOpening(webWalletURLs.CONNECT).then((newPeraWalletTab) => {
if (newPeraWalletTab && newPeraWalletTab.opener) {
appTellerManager.sendMessage({
message: {
type: "CONNECT",
data: {
...getMetaInfo(),
chainId
}
},

origin: webWalletURLs.CONNECT,
targetWindow: newPeraWalletTab,
timeout: 5000
});
}

const checkTabIsAliveInterval = setInterval(() => {
if (newPeraWalletTab?.closed === true) {
reject(
new PeraWalletConnectError(
{
type: "CONNECT_CANCELLED"
},
"Connect is cancelled by user"
)
);

clearInterval(checkTabIsAliveInterval);
onClose();
}

// eslint-disable-next-line no-magic-numbers
}, 2000);

appTellerManager.setupListener({
onReceiveMessage: (event: MessageEvent<TellerMessage<PeraTeller>>) => {
if (resolve && event.data.message.type === "CONNECT_CALLBACK") {
const accounts = event.data.message.data.addresses;

saveWalletDetailsToStorage(accounts, "pera-wallet-web");

resolve(accounts);

onClose();

newPeraWalletTab?.close();
} else if (event.data.message.type === "CONNECT_NETWORK_MISMATCH") {
reject(
new PeraWalletConnectError(
{
type: "CONNECT_NETWORK_MISMATCH",
detail: event.data.message.error
},
event.data.message.error ||
`Your wallet is connected to a different network to this dApp. Update your wallet to the correct network (MainNet or TestNet) to continue.`
)
);

onClose();

newPeraWalletTab?.close();
}
}
});
});
}

function onClose() {
removeModalWrapperFromDOM(PERA_WALLET_CONNECT_MODAL_ID);
}

return {
onWebWalletConnect
};
}

private async signTransactionWithMobile(signTxnRequestParams: PeraWalletTransaction[]) {
const formattedSignTxnRequest = formatJsonRpcRequest(
AlgorandMethod.SignTransaction, [signTxnRequestParams]
);
const formattedSignTxnRequest = formatJsonRpcRequest(AlgorandMethod.SignTransaction, [
signTxnRequestParams
]);
const walletDetails = getWalletDetailsFromStorage();

try {
Expand Down Expand Up @@ -516,7 +539,7 @@ class PeraWalletConnect {
chainId
}: {
// Converted Uint8Array data to base64
data: {data: string; message: string;}[];
data: {data: string; message: string}[];
signer: string;
chainId: AlgorandChainIDs;
}) {
Expand Down Expand Up @@ -578,7 +601,9 @@ class PeraWalletConnect {
}

if (!this.client) {
throw new Error("PeraWalletConnect was not initialized correctly while signing transaction.");
throw new Error(
"PeraWalletConnect was not initialized correctly while signing transaction."
);
}
}

Expand Down Expand Up @@ -620,7 +645,7 @@ class PeraWalletConnect {

const b64encodedData = data.map((item) => ({
...item,
data: Buffer.from(item.data).toString('base64')
data: Buffer.from(item.data).toString("base64")
}));

// Pera Mobile Wallet flow
Expand Down
9 changes: 6 additions & 3 deletions src/modal/PeraWalletConnectModal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,20 @@ export class PeraWalletConnectModal extends HTMLElement {
peraWalletConnectModalClassNames = `${peraWalletConnectModalClassNames} ${PERA_WALLET_MODAL_CLASSNAME}--compact`;
}

const singleAccount = this.getAttribute("single-account") === "true";
const selectedAccount = this.getAttribute("selected-account");

if (isMobile()) {
peraWalletConnectModal.innerHTML = `
<div class="${peraWalletConnectModalClassNames}">
<div class="pera-wallet-modal__body" part="body">
<pera-wallet-modal-header modal-id="${PERA_WALLET_CONNECT_MODAL_ID}"></pera-wallet-modal-header/>
<pera-wallet-modal-header modal-id="${PERA_WALLET_CONNECT_MODAL_ID}"></pera-wallet-modal-header>
<pera-wallet-modal-touch-screen-mode uri="${this.getAttribute(
"uri"
)}" should-use-sound="${this.getAttribute(
"should-use-sound"
)}"></pera-wallet-modal-touch-screen-mode>
)}" single-account="${singleAccount}" selected-account="${selectedAccount}"></pera-wallet-modal-touch-screen-mode>
</div>
</div>
`;
Expand All @@ -61,7 +64,7 @@ export class PeraWalletConnectModal extends HTMLElement {
"compact-mode"
)}" promote-mobile="${this.getAttribute(
"promote-mobile"
)}"></pera-wallet-modal-desktop-mode>
)}" single-account="${singleAccount}"></pera-wallet-modal-desktop-mode>
</div>
</div>
`;
Expand Down
9 changes: 7 additions & 2 deletions src/modal/mode/desktop/PeraWalletConnectModalDesktopMode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -300,12 +300,17 @@ export class PeraWalletModalDesktopMode extends HTMLElement {
}

renderQRCode() {
const URI = this.getAttribute("uri");
const isWebWalletAvailable = this.getAttribute("is-web-wallet-avaliable");
const isCompactMode = this.getAttribute("compact-mode") === "true";
const singleAccount = this.getAttribute("single-account") === "true";
let URI = this.getAttribute("uri");

if (singleAccount) {
URI = `${URI}&singleAccount=true`;
}

/* eslint-disable no-magic-numbers */
let size = isWebWalletAvailable === "false" ? 250 : 205;
let size = isWebWalletAvailable === "false" ? 250 : 215;

if (isCompactMode) {
size = 190;
Expand Down
Loading

0 comments on commit c0ef46f

Please sign in to comment.