Skip to content
Open
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
53 changes: 47 additions & 6 deletions src/helpers/aoconnect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,54 @@ export const results = (args: any) => {

export const connect = (args?: any) => {
const config = getAOConnectConfig();
return originalConnect({
MODE: 'mainnet',
MU_URL: config.MU_URL,
CU_URL: config.CU_URL,
// Support switching between mainnet and legacy via VITE_AO env var
// Default to mainnet for this branch
const aoMode = import.meta.env.VITE_AO || 'mainnet';
const defaultMode = aoMode === 'mainnet' ? 'mainnet' : 'legacy';

// If args already specifies MODE, use that; otherwise use the default from VITE_AO
const mode = args?.MODE || defaultMode;

// Log mode when connecting (only if not already specified in args to avoid duplicate logs)
if (!args?.MODE && mode === 'mainnet') {
console.log('🔗 AO Connect: Using MAINNET mode');
console.log(' CU_URL:', config.CU_URL);
console.log(' MU_URL:', config.MU_URL);
console.log(' GATEWAY_URL:', config.GATEWAY_URL);
} else if (!args?.MODE && mode === 'legacy') {
console.log('🔗 AO Connect: Using LEGACY mode');
}

// When MODE is 'mainnet', @permaweb/aoconnect should handle CU/MU URLs automatically
// Only pass them explicitly if in legacy mode or if explicitly provided in args
const connectConfig: any = {
MODE: mode,
GATEWAY_URL: config.GATEWAY_URL,
...args,
});
};

// Extract CU_URL and MU_URL from args if present (before spreading args)
const explicitCU = args?.CU_URL;
const explicitMU = args?.MU_URL;

// Only pass CU_URL and MU_URL if:
// 1. We're in legacy mode (need explicit testnet URLs), OR
// 2. They're explicitly provided in args (user override)
if (mode === 'legacy') {
// In legacy mode, use explicit testnet URLs
connectConfig.CU_URL = explicitCU || config.CU_URL;
connectConfig.MU_URL = explicitMU || config.MU_URL;
} else if (explicitCU || explicitMU) {
// In mainnet mode, only use CU/MU URLs if explicitly provided in args
if (explicitCU) connectConfig.CU_URL = explicitCU;
if (explicitMU) connectConfig.MU_URL = explicitMU;
}
// For mainnet mode without explicit CU/MU in args, don't pass them - let aoconnect handle automatically

// Apply all other args (excluding CU_URL/MU_URL which we've handled above)
const { CU_URL, MU_URL, ...otherArgs } = args || {};
Object.assign(connectConfig, otherArgs);

return originalConnect(connectConfig);
};

// Also export the original functions in case they're needed
Expand Down
45 changes: 41 additions & 4 deletions src/helpers/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,13 +106,50 @@ export const AO = {
export const HB = {
defaultNode: 'https://app-1.forward.computer',
};
export const AOCONFIG = {
cu_url: 'https://cu.ao-testnet.xyz',
cu_af_url: 'https://cu-af.dataos.so',

export const AO_NODE = {
// Mainnet HyperBEAM configuration
// Default URL: https://push.forward.computer (as per mainnet release notes)
url: import.meta.env.VITE_HYPERBEAM_URL || 'https://push.forward.computer',
// Mainnet scheduler: n_XZJhUnmldNFo4dhajoPZWhBXuJk-OcQr5JQ49c4Zo (schedule.forward.computer)
scheduler: import.meta.env.VITE_SCHEDULER || 'n_XZJhUnmldNFo4dhajoPZWhBXuJk-OcQr5JQ49c4Zo',
// Authority should be set per HyperBEAM node (found on hyperbuddy explorer or startup logs)
authority:
import.meta.env.VITE_AUTHORITY ||
import.meta.env.VITE_HYPERBEAM_AUTHORITY ||
'fcoN_xJeisVsPXA-trzVAuIiqO3ydLQxM-L4XbrQKzY',
};

// Support switching between mainnet and legacy CU/MU URLs
const getAOCONFIG = () => {
const aoMode = import.meta.env.VITE_AO || 'mainnet';

if (aoMode === 'mainnet') {
// For mainnet, use HyperBEAM infrastructure
// CU and MU are typically handled by the HyperBEAM gateway
// When MODE is 'mainnet', @permaweb/aoconnect should handle URLs automatically
// But we provide fallbacks if needed
return {
cu_url: import.meta.env.VITE_CU_URL || 'https://cu.ao-testnet.xyz', // Fallback, should be auto-handled by aoconnect
mu_url: import.meta.env.VITE_MU_URL || 'https://mu.ao-testnet.xyz', // Fallback, should be auto-handled by aoconnect
cu_af_url: 'https://cu-af.dataos.so',
gateway: 'https://arweave.net',
};
} else {
// Legacy/testnet configuration
return {
cu_url: 'https://cu.ao-testnet.xyz',
mu_url: 'https://mu.ao-testnet.xyz',
cu_af_url: 'https://cu-af.dataos.so',
gateway: 'https://arweave.net',
};
}
};

export const AOCONFIG = getAOCONFIG();

export const getAOConfig = () => {
return AOCONFIG;
return getAOCONFIG();
};

export const REFORMATTED_ASSETS = {
Expand Down
81 changes: 68 additions & 13 deletions src/providers/PermawebProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Loader } from 'components/atoms/Loader';
import { Panel } from 'components/molecules/Panel';
import { ProfileManage } from 'components/organisms/ProfileManage';
import { connect, createSigner } from 'helpers/aoconnect';
import { HB, STORAGE, TOKEN_REGISTRY } from 'helpers/config';
import { AO_NODE, HB, STORAGE, TOKEN_REGISTRY } from 'helpers/config';
import { clearTokenStatusCache } from 'helpers/tokenValidation';

import { useArweaveProvider } from './ArweaveProvider';
Expand Down Expand Up @@ -80,21 +80,76 @@ export function PermawebProvider(props: { children: React.ReactNode }) {
// const isInitialMount = React.useRef(true);

React.useEffect(() => {
const deps: any = {
ao: connect({ MODE: 'legacy' }),
arweave: Arweave.init({}),
signer: arProvider.wallet ? createSigner(arProvider.wallet) : null,
node: { url: HB.defaultNode },
};
try {
// Support switching between legacy and mainnet modes via VITE_AO env var
// Default to mainnet for this branch
const aoConnection = import.meta.env.VITE_AO || 'mainnet';

let signer = null;
if (arProvider.wallet) signer = createSigner(arProvider.wallet);

let ao: any;
if (aoConnection === 'mainnet') {
// Safety check: ensure AO_NODE is defined
if (!AO_NODE || !AO_NODE.url || !AO_NODE.scheduler) {
console.error('AO_NODE configuration is missing or incomplete:', AO_NODE);
// Fallback to legacy if mainnet config is missing
ao = connect({ MODE: 'legacy' });
console.warn('⚠️ Falling back to LEGACY mode due to missing AO_NODE configuration');
} else {
// In mainnet mode, pass SCHEDULER to connect() - it's used by spawn() calls
const config: any = { MODE: 'mainnet', URL: AO_NODE.url, SCHEDULER: AO_NODE.scheduler };
if (signer) config.signer = signer;
ao = connect(config);
console.log('🌐 BAZAR: Running in MAINNET mode');
console.log(' HyperBEAM URL:', AO_NODE.url);
console.log(' Scheduler:', AO_NODE.scheduler);
console.log(' Module:', process.env.MODULE);
console.log(' Profile Registry:', process.env.PROFILE_REGISTRY);
}
} else if (aoConnection === 'legacy') {
ao = connect({ MODE: 'legacy' });
console.log('🔵 BAZAR: Running in LEGACY mode (VITE_AO=legacy)');
} else {
console.warn('Unknown aoConnection mode, defaulting to mainnet:', aoConnection);
if (AO_NODE && AO_NODE.url && AO_NODE.scheduler) {
// In mainnet mode, pass SCHEDULER to connect() - it's used by spawn() calls
const config: any = { MODE: 'mainnet', URL: AO_NODE.url, SCHEDULER: AO_NODE.scheduler };
if (signer) config.signer = signer;
ao = connect(config);
console.log('🌐 BAZAR: Running in MAINNET mode (default)');
console.log(' HyperBEAM URL:', AO_NODE.url);
console.log(' Scheduler:', AO_NODE.scheduler);
} else {
ao = connect({ MODE: 'legacy' });
console.warn('⚠️ Falling back to LEGACY mode');
}
}

setLibs(PermawebLibs.init(deps));
setDeps(deps);
if (!ao) {
console.error('Failed to create AO connection');
return;
}

const deps: any = {
ao: ao,
arweave: Arweave.init({}),
signer: signer,
node: aoConnection === 'mainnet' && AO_NODE ? { ...AO_NODE } : { url: HB.defaultNode },
};

setLibs(PermawebLibs.init(deps));
setDeps(deps);

// Clear token status cache to ensure fresh data
clearTokenStatusCache();
// Clear token status cache to ensure fresh data
clearTokenStatusCache();

// Force refresh token balances
setToggleTokenBalanceUpdate((prev) => !prev);
// Force refresh token balances
setToggleTokenBalanceUpdate((prev) => !prev);
} catch (error) {
console.error('Error in PermawebProvider initialization:', error);
// Don't throw - allow app to render with null libs/deps
}
}, [arProvider.wallet]);

React.useEffect(() => {
Expand Down
7 changes: 3 additions & 4 deletions src/views/Profile/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,9 @@ export default function Profile() {

fetchedProfile = await permawebProvider.libs.getProfileById(address);

// If mainnet profile not found, try legacy as fallback
if (!fetchedProfile?.id || !fetchedProfile?.username) {
await new Promise((r) => setTimeout(r, 1000));
debug('Fetching legacy profile...');
debug('Mainnet profile not found, trying legacy...');
isLegacyProfile = true;
const aoProfile = AOProfile.init({ ao: connect({ MODE: 'legacy' }) });
fetchedProfile = await aoProfile.getProfileById({ profileId: address });
Expand Down Expand Up @@ -138,8 +138,7 @@ export default function Profile() {
return (
<ErrorWrapper>
<ErrorMessage>
Unable to load profile. This profile may not be hydrated on HyperBEAM yet, or there may be network issues on
legacynet.
Unable to load profile. This profile may not be hydrated on HyperBEAM yet, or there may be network issues.
</ErrorMessage>
<ErrorDetail>Profile ID: {address}</ErrorDetail>
</ErrorWrapper>
Expand Down
19 changes: 13 additions & 6 deletions vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ import { defineConfig } from 'vite';
import { nodePolyfills } from 'vite-plugin-node-polyfills';
import svgr from 'vite-plugin-svgr';

// Mainnet addresses (default for this branch)
const productionAddresses = {
MODULE: 'Pq2Zftrqut0hdisH_MC2pDOT6S4eQFoxGsFUzR6r350',
SCHEDULER: '_GQ33BkPtZrqxA84vM8Zk-N2aO0toNNu_C-l-rawrBA',
MODULE: 'ISShJH1ij-hPPt9St5UFFr_8Ys3Kj5cyg7zrMGt7H9s', // Mainnet AOS Module
SCHEDULER: 'n_XZJhUnmldNFo4dhajoPZWhBXuJk-OcQr5JQ49c4Zo', // Mainnet scheduler (schedule.forward.computer)
DEFAULT_TOKEN: 'xU9zFkq3X2ZQ6olwNVvr1vUWIjc3kXTWr7xKQD6dh10',
UCM: 'hqdL4AZaFZ0huQHbAsYxdTwG6vpibK7ALWKNzmWaD4Q',
UCM_ACTIVITY: '7_psKu3QHwzc2PFCJk2lEwyitLJbz6Vj7hOcltOulj4',
Expand All @@ -19,9 +20,10 @@ const productionAddresses = {
STAMPS: 'LaC2VtxqGekpRPuJh-TkI_ByAqCS2_KB3YuhMJ5yBtc',
};

// Legacy addresses (for fallback/testing)
const nonProductionAddresses = {
MODULE: 'Pq2Zftrqut0hdisH_MC2pDOT6S4eQFoxGsFUzR6r350',
SCHEDULER: '_GQ33BkPtZrqxA84vM8Zk-N2aO0toNNu_C-l-rawrBA',
MODULE: 'Pq2Zftrqut0hdisH_MC2pDOT6S4eQFoxGsFUzR6r350', // Legacy module
SCHEDULER: '_GQ33BkPtZrqxA84vM8Zk-N2aO0toNNu_C-l-rawrBA', // Legacy scheduler
DEFAULT_TOKEN: 'xU9zFkq3X2ZQ6olwNVvr1vUWIjc3kXTWr7xKQD6dh10',
UCM: 'CDxd81DDaJvpzxoyhXn-dVnZhYIFQEKU8FeUHdktFgQ',
UCM_ACTIVITY: 'W45ki8vJ0TcsxZAGZIbGj3k38595TA0HfZwCOaqhOa0',
Expand All @@ -38,7 +40,12 @@ export default defineConfig(({ mode }) => {
const isProduction = env === 'production';
const isStaging = env === 'staging';

const addresses = isProduction ? productionAddresses : isStaging ? nonProductionAddresses : productionAddresses;
// Support switching between mainnet and legacy via VITE_AO env var
// Default to mainnet for this branch
const aoMode = process.env.VITE_AO || 'mainnet';
const useMainnet = aoMode === 'mainnet';

const addresses = useMainnet ? productionAddresses : nonProductionAddresses;

return {
root: './',
Expand All @@ -56,7 +63,7 @@ export default defineConfig(({ mode }) => {
],
resolve: {
alias: {
'@permaweb/ucm': path.resolve(__dirname, 'node_modules/@permaweb/ucm/dist/browser.js'),
'@permaweb/ucm': path.resolve(__dirname, 'node_modules/@permaweb/ucm/dist/index.esm.js'),
api: path.resolve(__dirname, 'src/api'),
app: path.resolve(__dirname, 'src/app'),
arweave: path.resolve(__dirname, 'node_modules/arweave'),
Expand Down