Skip to content
Draft
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
2 changes: 1 addition & 1 deletion apps/browser-extension-wallet/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"permissions": ["webRequest", "storage", "tabs", "unlimitedStorage"],
"host_permissions": ["<all_urls>"],
"content_security_policy": {
"extension_pages": "default-src 'self' $LOCALHOST_DEFAULT_SRC; frame-src https://connect.trezor.io/ https://www.youtube-nocookie.com; script-src 'self' 'wasm-unsafe-eval'; font-src 'self' data: https://use.typekit.net; object-src 'self'; connect-src $MEMPOOLSPACE_URL $BLOCKFROST_URLS $MAESTRO_URLS $CARDANO_SERVICES_URLS $CARDANO_WS_SERVER_URLS $SENTRY_URL $DAPP_RADAR_APPI_URL https://coingecko.live-mainnet.eks.lw.iog.io https://coingecko.live-mainnet.eks.lw.iog.io https://muesliswap.live-mainnet.eks.lw.iog.io $LOCALHOST_CONNECT_SRC $POSTHOG_HOST https://use.typekit.net https://api.handle.me/ https://*.api.handle.me/ data:; style-src * 'unsafe-inline'; img-src * data: blob:;"
"extension_pages": "default-src 'self' $LOCALHOST_DEFAULT_SRC; frame-src https://connect.trezor.io/ https://www.youtube-nocookie.com; script-src 'self' 'wasm-unsafe-eval'; font-src 'self' data: https://use.typekit.net; object-src 'self'; connect-src $MEMPOOLSPACE_URL $BLOCKFROST_URLS $MAESTRO_URLS $CARDANO_SERVICES_URLS $CARDANO_WS_SERVER_URLS $SENTRY_URL $DAPP_RADAR_APPI_URL https://coingecko.live-mainnet.eks.lw.iog.io https://coingecko.live-mainnet.eks.lw.iog.io https://muesliswap.live-mainnet.eks.lw.iog.io $LOCALHOST_CONNECT_SRC $POSTHOG_HOST https://use.typekit.net https://api.handle.me/ https://*.api.handle.me/ https://*.pndsn.com data:; style-src * 'unsafe-inline'; img-src * data: blob:;"
},
"content_scripts": [
{
Expand Down
5 changes: 4 additions & 1 deletion apps/browser-extension-wallet/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@
"watch": " run-s cleanup:dist watch:project",
"watch:app": "run -T webpack --config webpack.app.dev.js --progress --watch",
"watch:sw": "run -T webpack --config webpack.sw.dev.js --progress --watch",
"watch:project": "run-p watch:sw watch:app"
"watch:project": "run-p watch:sw watch:app",
"subscribe": "ts-node scripts/subscribe.ts",
"publish": "ts-node scripts/publish.ts"
},
"dependencies": {
"@ant-design/icons": "^4.7.0",
Expand Down Expand Up @@ -144,6 +146,7 @@
"npm-run-all": "4.1.5",
"source-map-loader": "^5.0.0",
"text-encoding-utf-8": "^1.0.2",
"ts-node": "^10.9.2",
"tsconfig-paths-webpack-plugin": "3.5.2",
"web-ext": "^8.2.0",
"webassembly-loader-sw": "^1.1.0"
Expand Down
125 changes: 125 additions & 0 deletions apps/browser-extension-wallet/scripts/publish.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/* eslint-disable no-console */
/* eslint-disable @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires */
const path = require('path');
const dotenvDefaults = require('dotenv-defaults');
const { v4: uuidv4 } = require('uuid');

// Load environment variables
dotenvDefaults.config({
path: path.join(__dirname, '../.env'),
encoding: 'utf8',
defaults: path.join(__dirname, '../.env.defaults')
});

const SUBSCRIBE_KEY = process.env.PUBNUB_SUBSCRIBE_KEY;
const PUBLISH_KEY = process.env.PUBNUB_PUBLISH_KEY;
const USER_ID = process.env.PUBNUB_PUBLISH_USER_ID;
const CHANNEL = 'data.lace-wallet';
const PUBNUB_BASE_URL = 'https://ps.pndsn.com';
const PUBLISH_ENDPOINT = '/publish';
const JSON_INDENT = 2;

// Get message from command line arguments
// eslint-disable-next-line no-magic-numbers
const message = process.argv.slice(2).join(' ') || 'Test notification';

if (!PUBLISH_KEY || !USER_ID || !SUBSCRIBE_KEY) {
throw new Error(
'PUBNUB_PUBLISH_KEY, PUBNUB_PUBLISH_USER_ID and PUBNUB_SUBSCRIBE_KEY environment variables are required'
);
}

console.log(`Using User ID: ${USER_ID}`);
console.log(`Publishing message: "${message}"`);

interface TokenResponse {
token: string;
}

/**
* Requests a publish token from the PubNub token endpoint
*/
const requestPublishToken = async function requestPublishToken(): Promise<string> {
const url = `${PUBNUB_BASE_URL}/v1/blocks/sub-key/${SUBSCRIBE_KEY}/token/publisher`;

const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
publisherId: USER_ID,
publisherKey: PUBLISH_KEY
})
});

if (!response.ok) {
const errorText = await response.text();
throw new Error(
`Failed to get publish token: ${response.status} ${response.statusText} - ${errorText}. Request URL: ${url}`
);
}

const responseData: TokenResponse = await response.json();
console.log('Token response:', JSON.stringify(responseData, undefined, JSON_INDENT));
return responseData.token;
};

/**
* Publishes a message to the PubNub channel using HTTP REST API
*/
const publishMessage = async function publishMessage(token: string): Promise<void> {
const messageId = uuidv4();
const url = `${PUBNUB_BASE_URL}${PUBLISH_ENDPOINT}/${PUBLISH_KEY}/${SUBSCRIBE_KEY}/0/${CHANNEL}/0?auth=${encodeURIComponent(
token
)}`;

const messagePayload = {
title: message,
body: message,
id: messageId
};

console.log(`Publishing to URL: ${url}`);
console.log('Payload:', JSON.stringify(messagePayload, undefined, JSON_INDENT));
console.log('Token:', token);

const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(messagePayload)
});

if (!response.ok) {
const errorText = await response.text();
throw new Error(
`Failed to publish message: ${response.status} ${response.statusText} - ${errorText}. Request URL: ${url}`
);
}

const responseData = await response.json();
console.log('✅ Message published successfully!');
console.log('Response:', JSON.stringify(responseData, undefined, JSON_INDENT));
};

/**
* Main function to publish a message
*/
const main = async function main(): Promise<void> {
try {
console.log('Requesting publish token...');
const token = await requestPublishToken();
console.log('Token received successfully:', token);

console.log('Publishing message...');
await publishMessage(token);
} catch (error) {
console.error('Error:', error);
throw error;
}
};

// Run the script
main();
132 changes: 132 additions & 0 deletions apps/browser-extension-wallet/scripts/subscribe.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
/* eslint-disable no-console */
/* eslint-disable @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires */
const PubNub = require('pubnub');
const path = require('path');
const dotenvDefaults = require('dotenv-defaults');
const { v4: uuidv4 } = require('uuid');

// Load environment variables
dotenvDefaults.config({
path: path.join(__dirname, '../.env'),
encoding: 'utf8',
defaults: path.join(__dirname, '../.env.defaults')
});

const SUBSCRIBE_KEY = process.env.PUBNUB_SUBSCRIBE_KEY;
const USER_ID = process.env.PUBNUB_USER_ID || uuidv4();
const CHANNEL = 'data.lace-wallet';
const JSON_INDENT = 2;

if (!SUBSCRIBE_KEY) {
throw new Error('PUBNUB_SUBSCRIBE_KEY environment variable is required');
}

console.log(`Using User ID: ${USER_ID}`);

/**
* Requests a subscriber token from the PubNub token endpoint
*/
const requestSubscriberToken = async function requestSubscriberToken(): Promise<string> {
const url = `https://ps.pndsn.com/v1/blocks/sub-key/${SUBSCRIBE_KEY}/token/subscriber`;

const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
userId: USER_ID
})
});

if (!response.ok) {
const errorText = await response.text();
throw new Error(
`Failed to get subscriber token: ${response.status} ${response.statusText} - ${errorText}. Request URL: ${url}`
);
}

const data = (await response.json()) as { token: string };
return data.token;
};

/**
* Main function to subscribe to the PubNub channel
*/
const main = async function main(): Promise<void> {
try {
console.log('Requesting subscriber token...');
const token = await requestSubscriberToken();
console.log('Token received successfully');

console.log('Initializing PubNub...');
const pubnub = new PubNub({
subscribeKey: SUBSCRIBE_KEY,
userId: USER_ID,
authKey: token
});

// Add listener for messages
pubnub.addListener({
// eslint-disable-next-line @typescript-eslint/no-explicit-any
message: (messageEvent: any) => {
console.log('\n=== Message Received ===');
console.log('Channel:', messageEvent.channel);
console.log('Message:', JSON.stringify(messageEvent.message, undefined, JSON_INDENT));
console.log('Publisher:', messageEvent.publisher);
console.log('Subscription:', messageEvent.subscription);
console.log('Timestamp:', messageEvent.timetoken);
console.log('========================\n');
},
// eslint-disable-next-line @typescript-eslint/no-explicit-any
status: (statusEvent: any) => {
switch (statusEvent.category) {
case 'PNConnectedCategory':
console.log('✅ Successfully connected to PubNub');
break;
case 'PNReconnectedCategory':
console.log('🔄 Reconnected to PubNub');
break;
case 'PNDisconnectedCategory':
console.log('❌ Disconnected from PubNub');
break;
case 'PNUnknownCategory':
console.log('⚠️ Unknown status:', statusEvent);
break;
default:
console.log('Status:', statusEvent.category, statusEvent);
}
},
// eslint-disable-next-line @typescript-eslint/no-explicit-any
presence: (presenceEvent: any) => {
console.log('Presence event:', presenceEvent);
}
});

console.log(`Subscribing to channel: ${CHANNEL}...`);
await pubnub.subscribe({
channels: [CHANNEL]
});

console.log(`✅ Successfully subscribed to ${CHANNEL}`);
console.log('Listening for messages... (Press Ctrl+C to exit)\n');

// Keep the process alive
process.on('SIGINT', () => {
// console.log('\n\nUnsubscribing...');
// pubnub.unsubscribe({
// channels: [CHANNEL]
// });
// pubnub.destroy();
console.log('Goodbye!');
// eslint-disable-next-line no-process-exit
process.exit(0);
});
} catch (error) {
console.error('Error:', error);
throw error;
}
};

// Run the script
main();
Loading